【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退出for
            float3 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,得到一个居中的Bound
        dfpos = 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;//在结果上乘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;//累计到光
   
    }

    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中的各种关系

  1. 将这一部分RayMarching的参数折叠为RayMarchingParameter
    在这里插入图片描述
    在这里插入图片描述

  2. 打包环境和常量参数Constant
    在这里插入图片描述
    在这里插入图片描述

  3. 整理自阴影距离场的变量SelfShadow
    在这里插入图片描述
    在这里插入图片描述

  4. 打包投影的参数ShadowRayParameter
    在这里插入图片描述
    在这里插入图片描述

  5. 最后整理一下ShadowRayMarching输入顺序,按功能排序
    在这里插入图片描述


当前Shader

抄抄党注目

模型

在这里插入图片描述

长宽高100cm,轴居中,双面双材质ID的Cube模型

本文附下载

预览贴图

在这里插入图片描述

长宽高100cm,轴居中,双面双材质ID的Cube模型。

本文附下载

材质球

M_VolRayMarching
MI_VolRayMarching
MI_VolRayMarching_Shadow

父子关系
子实例材质
子实例材质
MI_VolRayMarching
M_VolRayMarching
MI_VolRayMarching_Shadow

在这里插入图片描述

M_VolRayMarching

细节

在这里插入图片描述

图表

在这里插入图片描述

MI_VolRayMarching

父材质为M_VolRayMarching

MI_VolRayMarching_Shadow

父材质为MI_VolRayMarching

  • 细节:
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/897348.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HBuilder X 中Vue.js基础使用1(三)

一、 模板语法 Vue 使用一种基于 HTML 的模板语法&#xff0c;使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML&#xff0c;可以被符合规范的浏览器和 HTML 解析器解析。 英文官网: Vue.js - The Progressive JavaScript Fr…

浪潮云启操作系统(InLinux)bcache缓存实践:理解OpenStack环境下虚拟机卷、Ceph OSD、bcache设备之间的映射关系

前言 在OpenStack平台上&#xff0c;采用bcache加速ceph分布式存储的方案被广泛用于企业和云环境。一方面&#xff0c;Ceph作为分布式存储系统&#xff0c;与虚拟机存储卷紧密结合&#xff0c;可以提供高可用和高性能的存储服务。另一方面&#xff0c;bcache作为混合存储方案&…

Turn-it:优化线材重构雕塑制造

&#x1f428;文章摘要abstract 电线雕塑在工业应用和日常生活中都很重要。 本文提出了一种新的制造策略&#xff0c;通过调整目标形状以适应电线弯曲机&#xff0c;然后由人工将其弯曲回目标形状。&#xff08;机器弯曲人工弯曲&#xff09; 该方法通过两阶段弯曲策略实现&a…

力扣——用队列实现栈(C语言)

目录 题目&#xff1a; 原理&#xff1a; 结构体MyStack 出栈void myStackPop(MyStack* obj) 入栈void myStackPush(MyStack* obj, int x) 读取栈顶元素int myStackTop(MyStack* obj) 判断栈空bool myStackEmpty(MyStack* obj) 销毁栈void myStackFree(MyStack* obj) 整…

NewStar CTF 2024 Week1,Week2部分

WP部分学习官方解题思路&#xff0c;这次比赛还是收获满满呀 web方向&#xff1a; headach3 抓包拿到flag 会赢吗 第一关&#xff1a; 查看源码看到flag第一部分和目录 第二关&#xff1a; 查看js文件 revealflag方法传入了一个className参数 <script>async func…

8.three.js相机详解

8.three.js相机详解 1、 认识相机 在Threejs中相机的表示是THREE.Camera&#xff0c;它是相机的抽象基类&#xff0c;其子类有两种相机&#xff0c;分别是正投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera&#xff1a; 正投影和透视投影的区别是&am…

燕山大学23级经济管理学院 10.18 C语言作业

燕山大学23级经济管理学院 10.18 C语言作业 文章目录 燕山大学23级经济管理学院 10.18 C语言作业1C语言的基本数据类型主要包括以下几种&#xff1a;为什么设计数据类型&#xff1f;数据类型与知识体系的对应使用数据类型时需要考虑的因素 21. 逻辑运算符2. 真值表3. 硬件实现4…

最大公约数(公式法)

求多个数的最大公约数 采用连续求gcd的方式 题目 ACCODE #include<bits/stdc.h> using namespace std; long long num[4]; int main(){cin>>num[1]>>num[2]>>num[3];sort(num1,num4);// cout<<num[1]<<" "<<num[2]<&…

尚硅谷spark学习

p4 快速上手 -开发环境准备

Java多线程新手指南:从零开始学习多线程创建,有两下子!

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴 bug菌&#xff0c;今天又来给大家手把手教学Java SE系列知识点啦&#xff0c;赶紧出来哇&#xff0c;别躲起来啊&#xff0c;听我讲干货记得点点赞&#xff0c;赞多了我就更有动力讲得更欢哦&#xff01;所以呀&…

代码审计-Python Flask

1.Jinjia2模版注入 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug &#xff0c;模板引擎则使用 Jinja2。jinja2是Flask作者开发的一个模板系统&#xff0c;起初是仿django模板的一个模板引擎&#xff0c;为Flask提供模板支持&#xff0c;由于…

KASan部署、使用与原理分析

文章目录 前言1、概述2、使用方法3、测试用例3.1、检测加载的内核模块3.2、检测调用的内核模块3.3、通过系统调用检测3.4、检测编译到Linux内核中的内核模块 4、工作原理4.1、影子内存&#xff08;Shadow Memory&#xff09;4.2、内存状态&#xff08;Memory States&#xff09…

海南聚广众达电子商务咨询有限公司靠谱吗怎么样?

在当今这个数字化浪潮席卷全球的时代&#xff0c;抖音电商以其独特的魅力成为了众多商家争相入驻的新蓝海。而在这片浩瀚的电商海洋中&#xff0c;如何找到一家既专业又可靠的合作伙伴&#xff0c;成为了众多商家心中的一大难题。今天&#xff0c;我们就来深入剖析一下海南聚广…

爬虫日常实战

爬取美团新闻信息&#xff0c;此处采用两种方法实现&#xff1a; 注意点&#xff1a;因为此处的数据都是动态数据&#xff0c;所以一定要考虑好向下滑动数据包会更新的情况&#xff0c;不然就只能读取当前页即第一页数据&#xff0c;方法一通过更新ajax数据包网址页数&#xf…

转变软件交付方式:通过统一 API 和测试策略提高质量和速度

API 在当今的数字化转型中至关重要&#xff0c;但无缝交付也同样重要。然而&#xff0c;许多组织仍然分散其 API 开发和 UI 测试流程&#xff0c;导致问题检测延迟、发布时间延长&#xff0c;甚至遗漏错误。在快节奏的环境中&#xff0c;这种方法是不可持续的&#xff0c;因为上…

Java调用上传文件接口

以 QAnthing 上传文件&#xff08;POST&#xff09;接口为例&#xff0c;展示Java如何调用上传文件接口。 接口文档如下&#xff1a; QAnthign接口文档地址 上代码&#xff1a; RestTemplate 版 /** * * param url 接口地址 * param filePath 文件本地路径 */ public vo…

【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅

文章目录 前言1. "引用"的概念1.1 "引用"的语法 2. "引用"的特性3. "引用"的使用场景3.1 "引用"做参数3. 2 "引用"做返回值3.2.1 "引用"做返回值时需要注意的点 4. 常引用5. "引用"在底层的实…

【设计模式系列】命令模式

目录 一、什么是命令模式 二、命令模式的角色 三、命令模式的典型应用场景 四、命令模式在Runnable中的应用 一、什么是命令模式 命令模式&#xff08;Command Pattern&#xff09;是一种行为设计模式&#xff0c;它将一个请求或简单操作封装为一个对象。这个模式提供了一种…

在使用new Date()生成时间戳时,发现数据库中 的时间总是多出一秒钟。

项目汇报的时候&#xff0c;进一步研究问题 insert into t_tax_file(task_id, task_no, business_type, file_name, file_url, creator_id, created_time, modifier_id,modified_time)value (10, taskNo测试, 1, 文件名称, 文件地址, 1, 2024-10-21 10:25:21.889, 1, 2024-10-…

CCF-BDCI大数据与计算智能大赛TOP4-京东生鲜

2023 CCF 大数据与计算智能大赛《线上线下全场景生鲜超市库存履约一体化决策》top4南山论剑 摘要1 数据预处理1.1 数据整合1.2 数据划分 2 特征工程2.1 静态特征2.2 动态特征 3 方案设计3.1 数据构造3.2 模型训练3.3 模型融合3.4库存分配3.5 方案对比 链接: CCFBDCI-线上线下全…