ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

volsample RayMarchCore.cginc 精读:结构化光线步进的起点偏移与步长计算

volsample RayMarchCore.cginc 精读:结构化光线步进的起点偏移与步长计算 volsample RayMarchCore.cginc 精读结构化光线步进的起点偏移与步长计算【免费下载链接】volsampleStructured Volume Sampling - sample placement algorithm for real-time volume rendering with low aliasing, for camera-in-volume case.项目地址: https://gitcode.com/gh_mirrors/vo/volsamplevolsample 是一个开源的结构化体积采样Structured Volume Sampling项目专门解决相机位于体积内部时实时体渲染的严重混叠问题。它的核心思想写在 RayMarchCore.cginc 里不再让采样层跟着相机跑而是把采样点钉在世界空间的一组平行平面上。本文带你精读这份文件重点拆解结构化光线步进structured raymarching中最关键的两个参数——起点偏移 t_0 与步长 dt——是如何一步步计算出来的读完你就能自己读懂并复用这套思路。为什么要做结构化采样先看混叠从哪来实时体渲染里采样次数很少例如云场景只有 32 次见 SceneClouds.cginc当相机在体积内部移动时采样点如何放置直接决定画面是否稳定。RayMarchCore.cginc 里实现了三种方案正好构成一条演进脉络采样方案采样层如何放置相机平移时相机旋转时对应函数固定 Z 采样垂直于视线、跟随相机采样层横扫体积混叠严重 相对稳定RayMarchFixedZ固定 Z 固定采样只补偿前向平移前向移动稳定视锥横扫侧面采样层RayMarchFixedZPinned结构化采样世界空间固定平面族采样只在平面内滑动几乎无混叠 ✅多射线混合补偿RaymarchStructured结构化采样的妙处在于相机平移时采样点只在自己所在的平面内平行滑动而平面本身在空间中是密集采样的滑动不会引入可见的走样。这也是标题里起点偏移与步长计算的用武之地。IntersectPlanes 精读两个公式搞定采样布局结构化采样把体积剖成一组间距固定的世界空间平面族间距为SAMPLE_PERIOD平面法线 n 来自十二面体五边形面的朝向。光线ro t * rd与这些平面的交点就是采样点。计算这些交点只需要 IntersectPlanes 这个十几行的函数void IntersectPlanes( in float3 n, in float3 ro, in float3 rd, out float t_0, out float dt ) { float ndotrd dot( rd, n ); dt SAMPLE_PERIOD / abs( ndotrd ); // 步长 t_0 -fmod( dot( ro, n ), SAMPLE_PERIOD ) / ndotrd; // 起点偏移 if( t_0 0. ) t_0 dt; // 保证首样本在视线前方 }步长 dt入射角的自动补偿 第一个公式dt SAMPLE_PERIOD / |dot(rd, n)|。光线垂直射向平面族时ndotrd ±1步长正好等于SAMPLE_PERIOD当视线倾斜掠射时|ndotrd| 1dt 自动变大。这是因为光线参数 t 是沿光线的距离而平面族是世界空间等距的两者之间隔着夹角。除以|ndotrd|后无论视线从哪个方向穿过体积采样点在世界空间都严格等间距——这就是结构化三个字的含义采样密度由世界空间决定与视角无关。起点偏移 t_0把第一条射线对齐到分层 第二个公式t_0 -fmod(dot(ro, n), SAMPLE_PERIOD) / ndotrd稍显晦涩拆开看就清楚了dot(ro, n)是相机到过原点参考平面的带符号距离fmod(..., SAMPLE_PERIOD)取余数得到相机与上一片采样平面之间的残余距离再除以ndotrd把这段空间距离换算成光线参数 t负号把它翻转为到下一片平面的参数距离。最后一行if(t_0 0.) t_0 dt处理了一个隐蔽的坑GPU 的fmod对负数参数行为不一这行代码统一了行为并保证第一个采样点永远落在视点前方不会出现背后采样的鬼影。RaymarchStructured把三条光线缝合成一帧单个平面法线只在部分像素上成立。倒角十二面体把屏幕分成三种区域五边形面1 条射线、倒角棱2 条射线混合、倒角顶点3 条射线混合分别对应 VolumeRender.shader 的三个 Pass。真正的整合在 RaymarchStructured 中完成首样本淡入淡出firstWt t / dt给第一片采样加权。注释里说得很直白——不做这步会在画面里看到恼人的五边形伪影隐形墙zbuf min(depth, dt * SAMPLE_COUNT)在体积尽头假设一堵不可见墙让采样在远处平滑淡出权重混合最终结果sum wt.x*sum0 wt.y*sum1 wt.z*sum2三个权重恰好对应十二面体网格顶点色里的 RGB见 PlatonicSolidBlend.cs。数据从哪来一整套闭环的调用链法线 n 与权重 wt 不是硬编码在着色器里的而是由 PlatonicSolidBlend.cs 实时构造的倒角十二面体网格携带法线编码进三组 UV权重写进顶点色VolumeRender.shader 的顶点着色器再用 Spheremap Transform 解码还原。整个流程由 StructuredVolumeSampling.cs 的OnRenderImage驱动三 Pass 依次绘制网格的三个子网格。想验证每一步可以打开 sponza.unity 或 clouds.unity 场景在 Inspector 里调PlatonicSolidBlend的 bevel 值或切换 VolumeRender.shader 里的DEBUG_BEVEL、Z_PLANES_ONLY宏观察分层效果。小结回到开头的问题为什么结构化采样能消除体渲染混叠答案就藏在这两个公式里——dt保证世界空间采样间距恒定t_0保证每条光线都从正确的分层起点出发。这两行代码加上十二面体提供的多方向平面族和权重混合构成了 volsample 全部魔法的基础。如果你正在做实时体积渲染、体积云或体雾不妨从 RayMarchCore.cginc 开始读起它不到 220 行却是理解体渲染抗锯齿的一条捷径。【免费下载链接】volsampleStructured Volume Sampling - sample placement algorithm for real-time volume rendering with low aliasing, for camera-in-volume case.项目地址: https://gitcode.com/gh_mirrors/vo/volsample创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表