【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第六篇-阶段总结篇】
因为马上就要进入下一个阶段,制作动态编辑体积纹理的模块。
但在这之前,要在这一章做最后一些整理。
- 首先,我们完成没完成的部分。
- 其次,最后整理一下图表。
- 最后,本文附上正在用的贴图
完善Shader
还记得我们之前注释掉了"阶梯纹理修复"的部分吗?


在第二章第七节中,我们已经修复了这个阶梯纹理。
CurPos += LocalCamVec * (1 - FinalStepSize);//只留了它
然而,在第三章对Shader进行大幅修改时,我们暂时将其注释掉并未继续处理。现在,我们将重新着手修复这个阶梯纹理问题。
希望你还记得,修复阶梯纹理的原理是将for循环的一步单独再以一个小步FinalStepSize执行一次。
因此,基本上就是将for循环中的内容复制出来,在for之后再运行一次。
//创建变量,从0开始累加沿相机方向步进过程中的总密度
float accumdens = 0;//Shadow部分
//创建变量,透射率和光线的能量
float transmittance =1;
float3 lightenergy = 0;
//基本和相机方向步进一样,但这些都是常量,不需要写进for里
Density *= StepSize;
LightVector *= ShadowStepSize;
ShadowDensity *= ShadowStepSize;
//一个对数来计算阈值,用来判断光线是否还值得计算
float shadowthresh = -log(ShadowThreshold)/ShadowDensity;//使用 MaxSteps 作为最大步数进行循环,每次循环执行以下操作
for (int i = 0; i < MaxSteps; i++)
{float cursample = PseudoVolumeTexture(Tex, TexSampler, saturate(CurPos), XYFrames, NumFrames).r;// 在当前步进位置进行纹理采样//Shadow部分if(cursample > 0.001)//如果采样位置没有密度,则跳过{float3 Lpos = CurPos;//Lpos将作为光线步进的起始位置float shadowdist = 0;//和之前的accumdens一样,积累阴影//自阴影for(int s = 0; s < ShadowSteps; s++){Lpos += LightVector;//移动步进位置float Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;//采样//判断是否在框内,不是则直接break退出forfloat3 shadowboxtest = floor( 0.5+ (abs(0.5-Lpos)));//float exitshadowbox = shadowboxtest.x + shadowboxtest.y + shadowboxtest.z;float exitshadowbox = dot(shadowboxtest,1);//简短的通道相加if(shadowdist > shadowthresh || exitshadowbox >= 1) break;shadowdist += Lsample;//累计}//接收阴影float3 dfpos = 2 * (CurPos -0.5) * LocalObjectBoundsMax;//-0.5 * 2,得到一个居中的Bounddfpos = LWCToFloat(TransformLocalPositionToWorld(Parameters,dfpos)) - CameraPosWS;//将dfpos转换为世界空间,需要LWC精度所以在代码里转换,减去相机位置float dftracedist = 1; //创建四个变量float dfshadow = 1;//这是我们最终要的float curdist = 0;float DistanceAlongTrace = 0;for (int d = 0; d < DFSSteps; d++)//又一次的光线步进{DistanceAlongTrace += curdist;//增加距离curdist = GetDistanceToNearestSurfaceGlobal(dfpos);//采样全局距离场,他和蓝图里`DistanceToNearestSurface`是相同函数float SphereSize = DistanceAlongTrace * LightTangent;//采样距离场软阴影的球形距离dfshadow = min( saturate(curdist/SphereSize),dfshadow);//用小于它的结果来更新变量dfpos.xyz += LightVectorWS * dftracedist * curdist;//继续移动位置dftracedist *= 1.0001;//增加一个很小的因子}//更新样本和光能,算法是BeersLaw函数cursample = 1 -exp(-cursample * Density);lightenergy += exp(-shadowdist * ShadowDensity) * cursample * transmittance * LightColor * dfshadow;//在结果上乘dfshadowtransmittance *= 1-cursample;//环境光照部分shadowdist = 0;//重置一下阴影距离,继续利用它计算光照Lpos = CurPos + float3(0,0,0.025);//新位置float Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;//采样shadowdist += Lsample;Lpos = CurPos + float3(0,0,0.05);Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;//采样shadowdist += Lsample;Lpos = CurPos + float3(0,0,0.15);Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;//采样shadowdist += Lsample;lightenergy += exp(-shadowdist * AmbientDensity) *cursample * SkyColor * transmittance;//累计到光}CurPos += -LocalCamVec;
}CurPos += LocalCamVec * (1 - FinalStepSize);
float cursample = PseudoVolumeTexture(Tex, TexSampler, saturate(CurPos), XYFrames, NumFrames).r;//从上面复制过来,使用 FinalStepSize 结果再 Step 一次,进行阶梯修复if(cursample > 0.001){float3 Lpos = CurPos;float shadowdist = 0;for(int s = 0; s < ShadowSteps; s++){Lpos += LightVector;float Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;float3 shadowboxtest = floor( 0.5+ (abs(0.5-Lpos)));float exitshadowbox = dot(shadowboxtest,1);if(shadowdist > shadowthresh || exitshadowbox >= 1) break;shadowdist += Lsample;}float3 dfpos = 2 * (CurPos -0.5) * LocalObjectBoundsMax;dfpos = LWCToFloat(TransformLocalPositionToWorld(Parameters,dfpos)) - CameraPosWS;float dftracedist = 1; float dfshadow = 1;float curdist = 0;float DistanceAlongTrace = 0;for (int d = 0; d < DFSSteps; d++){DistanceAlongTrace += curdist;curdist = GetDistanceToNearestSurfaceGlobal(dfpos);float SphereSize = DistanceAlongTrace * LightTangent;dfshadow = min( saturate(curdist/SphereSize),dfshadow);dfpos.xyz += LightVectorWS * dftracedist * curdist;dftracedist *= 1.0001;}cursample = 1 -exp(-cursample * Density);lightenergy += exp(-shadowdist * ShadowDensity) * cursample * transmittance * LightColor * dfshadow;transmittance *= 1-cursample;shadowdist = 0;Lpos = CurPos + float3(0,0,0.025);float Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;shadowdist += Lsample;Lpos = CurPos + float3(0,0,0.05);Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;shadowdist += Lsample;Lpos = CurPos + float3(0,0,0.15);Lsample = PseudoVolumeTexture(Tex, TexSampler, saturate(Lpos), XYFrames, NumFrames).r;shadowdist += Lsample;lightenergy += exp(-shadowdist * AmbientDensity) *cursample * SkyColor * transmittance;}return float4(lightenergy, transmittance);
整理图表
老样子,我们做整理,消除意大利面可以让我们更直观的感受shader中的各种关系
-
将这一部分
RayMarching的参数折叠为RayMarchingParameter


-
打包环境和常量参数
Constant


-
整理自阴影距离场的变量
SelfShadow


-
打包投影的参数
ShadowRayParameter


-
最后整理一下
ShadowRayMarching输入顺序,按功能排序

当前Shader
抄抄党注目
模型

长宽高100cm,轴居中,双面双材质ID的Cube模型
本文附下载
预览贴图

长宽高100cm,轴居中,双面双材质ID的Cube模型。
本文附下载
材质球
M_VolRayMarching
MI_VolRayMarching
MI_VolRayMarching_Shadow

M_VolRayMarching
细节

图表

MI_VolRayMarching
父材质为M_VolRayMarching
MI_VolRayMarching_Shadow
父材质为MI_VolRayMarching
- 细节:

相关文章:
【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第六篇-阶段总结篇】
因为马上就要进入下一个阶段,制作动态编辑体积纹理的模块。 但在这之前,要在这一章做最后一些整理。 首先,我们完成没完成的部分。其次,最后整理一下图表。最后,本文附上正在用的贴图 完善Shader 还记得我们之前注…...
地球村上一些可能有助于赚钱的20个思维方式
地球村上一些可能有助于赚钱的20个思维方式: 1. 目标导向思维:明确自己的财务目标,并制定详细、可执行的计划来逐步实现。 2. 创新思维:不断寻求新的商业机会和独特的解决方案,以在竞争激烈的市场中脱颖而出。 3. 价值…...
0基础入门matlab
目录 一、命令 二、变量命名 三、数据类型 数字 字符和字符串 矩阵 rand、randi和randn的区别? 元胞数组和结构体 MAGIC 结构体 四、矩阵构造、四则运算、矩阵下标 五、MATLAB逻辑与流程控制 六、MATLAB绘图 二维平面绘图 三维平面绘图 导出图片 内…...
【前端】实操tips集合
1. 关闭vue中组件名字的多词校验 (1) package.json文件中修改eslint配置 "eslintConfig": {"rules": {"vue/multi-word-component-names":"off" }}, (2).eslintrc.js或者.eslintrc配置文件中进行配置 modu…...
基于Springboot+Vue 传统文化管理系统(源码+LW+部署讲解+数据库+ppt)
!!!!!!!!! 会持续一直更新下去 有问必答 一键收藏关注不迷路 源码获取:https://pan.baidu.com/s/1aRpOv3f2sdtVYOogQjb8jg?pwdjf1d 提取码: jf1d &#…...
质量漫谈一
我知道很多同学看到这类问题,第一反应想要去寻找的就是作为测试角色,应该要如何如何去做?但是今天这里作为质量第一篇,不打算按照这样单角度去写,这类同学可以就此打住,如果在意的话,可关注后续…...
个体化神经调控 Neurolnavigation介绍
神经调控技术包括DBS, TMS, rTMS, tDCS等等。今天主要说一下TMS。 TMS全程经颅磁刺激,通过对头皮放置磁场线圈,可以定向的往局部头皮发送脉冲信号,抑制局部神经元活动。 TMS的优点是精准刺激,tDCS的优点是刺激范围比较宽泛。近期有…...
02-RT1060 双ADC采样+eDMA传输
RT1060-双ADC+eDMA外设的配合使用 该项目是基于MIMXRT1060-EVKB官方开发板编写的驱动。 一、头文件包含介绍 #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_adc.h" #include "fsl_adc_et…...
单值集合总复习
1:Object类的核心方法复习 Object 是所有类【引用数据类型】的 直接 / 间接 父类 toString(): 将一个 引用数据类型的对象 转换成 String 类型 class Object{//Sun //toString()不需要参数:将一个对象转换成字符串 将调用者转换成字符串 public String …...
Pyside6 布局管理器(4)--- QGridLayout的使用
一、QGridLayout的介绍(官翻) QGridLayout 获得可用的空间(由其父布局或 parentWidget() 提供),将其划分为行和列,并将其管理的每个小部件放入正确的单元格中。 列和行的行为是相同的;我们将…...
从GPT定制到Turbo升级再到Assistants API,未来AI世界,你准备好了吗?
引言 在OpenAI DevDay发布会上,OpenAI再次震撼整个人工智能行业,为AI领域带来了重大的更新。CEO Sam Altman宣布推出了定制版本的ChatGPT,这意味着用户现在可以根据自己的需求打造个性化的GPT,并分享至GPT Store。这一消息对于受…...
「漏洞复现」BladeX企业级开发平台 tenant/list SQL 注入漏洞复现(CVE-2024-33332)
0x01 免责声明 请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。工具来自网络,安全性自测,如有侵权请联系删…...
基于SSM的消防物资存储系统【附源码】
基于SSM的消防物资存储系统 效果如下: 用户功能界面 仓库管理界面 物资入库管理界面 物资出库管理界面 物资详情管理界面 报警通知管理界面 安全检查提醒管理界面 管理员功能界面 研究背景 21世纪,我国早在上世纪就已普及互联网信息,互联网…...
Pseudo Multi-Camera Editing 数据集:通过常规视频生成的伪标记多摄像机推荐数据集,显著提升模型在未知领域的准确性。
2024-10-19,由伊利诺伊大学厄巴纳-香槟分校和香港城市大学的研究团队提出了一种创新方法,通过将常规视频转换成伪标记的多摄像机视角推荐数据集,有效解决了在未知领域中模型泛化能力差的问题。数据集的创建,为电影、电视和其他媒体…...
认识一下 Mochi-1--最新的免费开源人工智能视频模型
Genmo 是一家专注于视频生成的人工智能公司,该公司宣布发布 Mochi 1 的研究预览版。Mochi 1 是一种新的开源模型,可根据文本提示生成高质量视频,其性能可与 Runway 的 Gen-3 Alpha、Luma AI 的 Dream Machine、Kuaishou 的 Kling、Minimax 的…...
Spring 的事务传播机制
Spring 的事务传播机制定义了一个事务方法在遇到已经存在的事务时如何处理。事务传播属性(Propagation)提供了七种机制,以适应不同的业务需求和事务边界管理。 1. Spring 的事务传播机制的类型 (1)REQUIREDÿ…...
线性代数(1)——线性方程组的几何意义
线性代数的基本问题是求解个未知数的个线性方程; 例如:(方程1)。 在线性代数的第一讲中,我们从Row Picture、Column Picture、Matrix Picture三个角度来看这个问题。 上面的系统是二维的。通过添加第三个变量&#…...
写给自己的一些心得体会
为什么是CSDN??? 最近跑实验跑得绝望,感觉自己兜兜转转走了太多太多的弯路,我不知道这样的弯路什么时候是个尽头,就像在USJ排队,看似好像要到入口了,实则一转头还是无尽绵延的队伍。走了这么多弯路,总要…...
论文阅读(二十九):Multi-scale Interactive Network for Salient Object Detection
文章目录 Abstract1.Introduction2.Scale VariationProposed Method3.1Network Overview3.2Aggregate Interaction Module3.3 Self-Interaction Module3.4Consistency-Enhanced Loss 4.Experiments4.1Implementation Details4.2 Comparison with State-of-the-arts4.3Ablation …...
常见存储器及其特点
: 一、只读存储器(ROM)及其类型 1. ROM 特点:存储的数据固定不变,只能读出不能写入,且断电后数据不丢失。应用:通常用于存储系统程序,如BIOS等。 2. PROM(可编程只读…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
