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

  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

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

『完整代码』坐骑召唤

创建一个按钮 作为召唤/消失坐骑的开关 将预制体放入指定文件夹 命名为Mount01 创建脚本并编写&#xff1a;CallMount.cs using UnityEngine; using UnityEngine.UI; public class CallMount : MonoBehaviour{public Button callBtn;GameObject mountPrefab;GameObject mountIn…

嵌套div导致子区域margin失效问题解决

嵌套div导致子区域margin失效问题解决 现象原因解决方法 现象 <div class"prev"></div> <div class"parent"><div class"child"></div><div class"child"></div> </div> <div cl…

Netty无锁化设计之对象池实现

池化技术是比较常见的一种技术&#xff0c;在平时我们已经就接触很多了&#xff0c;比如线程池&#xff0c;数据库连接池等等。当我们要使用一个资源的时候从池中去获取&#xff0c;用完就放回池中以便其他线程可以使用&#xff0c;这样的目的就是为了减少资源开销&#xff0c;…

MySQL-23.多表查询-内连接

一.内连接 -- 多表查询 select * from tb_emp,tb_dept where tb_emp.dept_id tb_dept.id;-- 内连接 -- A.查询员工的姓名&#xff0c;及所属的部门名称&#xff08;隐式内连接实现&#xff09; select tb_emp.name as 员工姓名,tb_dept.name as 部门名称 from tb_emp,tb_dep…

简单介绍冯诺依曼体系

现代的计算机, 大多遵守冯诺依曼体系结构 CPU中央处理器&#xff1a;进行算术运算和逻辑判断。存储器&#xff1a;分为外存和内存&#xff0c;用于存储数据&#xff08;使用二进制方式存储&#xff09;。输入设备&#xff1a;用户给计算机发号施令。输出设备&#xff1a;计算机…

RISC-V笔记——Pipeline依赖

1. 前言 RISC-V的RVWMO模型主要包含了preserved program order、load value axiom、atomicity axiom、progress axiom和I/O Ordering。今天主要记录下preserved program order(保留程序顺序)中的Pipeline Dependencies(Pipeline依赖)。 2. Pipeline依赖 Pipeline依赖指的是&a…

LeetCode_2520. 统计能整除数字的位数_java

1、题目 2520. 统计能整除数字的位数https://leetcode.cn/problems/count-the-digits-that-divide-a-number/ 给你一个整数 num &#xff0c;返回 num 中能整除 num 的数位的数目。 如果满足 nums % val 0 &#xff0c;则认为整数 val 可以整除 nums 。 示例 1&#xff1a;…

TiDB替换Starrocks:业务综合宽表迁移的性能评估与降本增效决策

作者&#xff1a; 我是人间不清醒 原文来源&#xff1a; https://tidb.net/blog/6638f594 1、 场景 业务综合宽表是报表生成、大屏幕展示和数据计算处理的核心数据结构。目前&#xff0c;这些宽表存储在Starrocks系统中&#xff0c;但该系统存在显著的性能瓶颈。例如&#…

如何实现金蝶商品数据集成到电商系统的SKU

如何实现金蝶商品数据集成到电商SKU系统 金蝶商品数据集成到电商SKU的技术实现 在现代企业的数据管理中&#xff0c;系统间的数据对接与集成是提升业务效率和准确性的关键环节。本文将分享一个实际案例&#xff1a;如何通过轻易云数据集成平台&#xff0c;将金蝶云星辰V2中的商…

实战华为AC6508无线控制器+华为无线AP上线配置(AirEngine5762S-12+AirEngine5760-10)+无线WIFI配置

一、适用场景 1、适用于企业环境、校园环境、大户型家庭多层楼环境。 2、对于无线网络需要集中管理和监测的环境&#xff0c;无线wifi覆盖范围面积大&#xff0c;适用本实例。 3、当无线WIFI需要从一个区域到另一个区域无缝漫游时&#xff0c;确保应用不掉线&#xff0c;可使用…

简单有效修复d3d9.dll错误,11种d3d9.dll错误详细解决办法教程

当你遇到d3d9.dll文件丢失的问题时&#xff0c;可以通过今天的这篇文章详细的步骤来尝试修复这个问题&#xff0c;今天将教大家十一种d3d9.dll丢失修复的方法。 1. 重新安装DirectX以恢复d3d9.dll d3d9.dll是DirectX的一部分&#xff0c;因此重新安装DirectX通常可以解决d3d9.…

C#描述-计算机视觉OpenCV(7):MSER特征检测

C#描述-计算机视觉OpenCV&#xff08;7&#xff09;&#xff1a;MSER特征检测 基本概念操作实例效果优化 基本概念 前文C#描述-计算机视觉OpenCV&#xff08;6&#xff09;&#xff1a;形态学描述了如何对图像的前后景特征形态进行检测与运算&#xff0c;本篇将分析基于形态的…

Safari 中 filter: blur() 高斯模糊引发的性能问题及解决方案

目录 引言问题背景&#xff1a;filter: blur() 引发的问题产生问题的原因分析解决方案&#xff1a;开启硬件加速实际应用示例性能优化建议常见的调试工具与分析方法 引言 在前端开发中&#xff0c;CSS滤镜&#xff08;如filter: blur()&#xff09;的广泛使用为页面带来了各种…

大数据-173 Elasticsearch 索引操作 增删改查 详细 JSON 操作

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

后台管理员登录实现--系统篇

我的小系统后台原来就有一个上传图片的功能还夹带个删除图片的功能&#xff0c;还嵌到了一个菜单里面。之前效果如下 那么现在为了加大安全力度&#xff0c;想增加一个登录页面。通过登录再到这个页面。看着貌似很简单&#xff0c;但是听我细细说来&#xff0c;要新增些什么东西…

KMP 算法

目录 KMP 算法 算法思路 为什么不需要在主串中进行回退 计算 next 数组 代码实现 next 数组优化 查找所有起始位置 KMP 算法 KMP 算法是一种改进的字符串匹配算法&#xff0c;由 D.E.Knuth&#xff0c;J.H.Morris 和 V.R.Pratt 提出的&#xff0c;因此人们称它为 克努特…

(北京政务服务满意度公司)满意度调查助力服务质量提升

在当今社会&#xff0c;&#xff08;政务服务满意度公司&#xff09;政务窗口服务的质量直接关系到市民的日常生活和城市的健康发展。为了解市民对政务窗口服务的满意度&#xff0c;提升服务质量&#xff0c;某市委托民安智库专业市场调查公司开展了政务窗口服务满意度调查&…

【平方矩阵 + 蛇形矩阵】

矩阵找规律题 题目链接&#xff1a; 平方矩阵 I平方矩阵 II平方矩阵 III蛇形矩阵 平方矩阵 I 解法一&#xff1a;找坐标规律 while True:x int(input())if not x:breakfor i in range(x):for j in range(x):print(%d % min(i 1, j 1, x - i, x - j), end )print()prin…

【Hive】3-HiveSQL 数据定义语言(DDL)

HiveSQL 数据定义语言&#xff08;DDL&#xff09; SQL中DDL语法的作用 数据定义语言(Data Definition Language&#xff0c;DDL)&#xff0c;是SQL语言集中对数据库内部的对象结构进行创建&#xff0c;删除&#xff0c;修改等的操作语言&#xff0c;这些数据库对象包括datab…

SpringBoot实现的汽车票在线预订系统

2相关技术 2.1 MySQL 数据库 MySQL 是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非…