目的:

最近接触一些分形Shader。自己实现了一个2D fbm,感觉很好看。然后又看到人家三维的分形,看起来很棒,心里痒痒。

影视大作和网上一堆令人惊叹的分形艺术,我也不再多说了。

本篇旨在对在ue4中实现分形的第一步,RayTrace和RayMarch加以具体解释,然后给出一个最简单的RayMarch材质,便于读者扩展。

(RayMarch一个球形“云”)

参考:

我之前对一篇ShaderToy的解析

观察:

1.分形是什么?它有什么实际意义?

分形指缩放之后还自相似的图形。

分形的特点,在于以极少的初始条件产生极丰富的信息。大自然也处处是分形。

分形的意义在整个科学里比较松散。分形在上世纪最热的时候,人们预言称21世纪是“分形的世纪”。(像不像现在的人工智能?)事实证明人类至今还对其知之甚少,难以研究。现在,凉到了正常水平。

除了帅以外,分形的几个实际应用:

1.海岸线估计:数据证明海岸线具有自相似性,所以只要给出一个粗略的海岸线轮廓,再进行分形后计算长度,就能估算实际的海岸线长度。
2.图片超分辨率,压缩...
3.混沌理论

2.简述RayTrace,RayTrace实际意义,什么时候该用哪个?

RayMarch:沿着视线,每隔一小步长收集此点颜色信息,最终累加。不反射视线。
RayTrace:沿着视线,看是否与场景相交,在交点处计算颜色(光照模型,阴影...),并反/折/衍射

因为RayMarch在交线段上每一个步长都要收集信息,所以肯定处理半透明的,有体积的东西。常见如体积云,体积阴影...

因为它计算量大,效果好,只有在特别追求效果或互动的时候,才用它。

RayTrace不用多说,一般的透明半透明场景。现在显卡也支持硬件光追,十分提升场景的真实感。也许也可以应用更多PBR算法了。

3.为什么想要RayTrace分形,却先RayMarch?

RayMarch:沿着视线收集信息,不反射
RayTrace:沿着视线,碰到立马求颜色,并反/折/衍射

你看,他们的关键都是沿着视线去收集,区别不大。

而且你会发现很多问题是两者的混合。比如我们之后RayTrace Julia Set的时候,由于不能得到Julia Set分形的解析式,只能通过Distance Estimate 慢慢“RayMarch”直到十分接近分形表面,再进行RayTrace。

所以,拿到距离场再进行RayMarch,到达表面再进行RayTrace,是现代渲染的基本操作。

分析:

1.March

现在,我们来RayMarch一个中心在圆点,半径为100的云球。

简单起见,我们不作其他判断,暴力地每一个步长都判断。

伪代码

伪代码
float re=0;
for(int t=0;t<3000;t++)
{NowPos = CamPos + viewDir * t * Step;if(NowPos在球内){//gain也可换成其他值,比如0.0001re+=1/3000.0f;}
}
return re;

显而易见,当越接近边缘,视线穿过的“云点”越少,就显得越薄。

最重要的问题来了,上面的伪代码中,在ue4中,这个viewDir怎么计算?

2.NDC空间

标准化设备坐标空间(Normalized Device Coordinates,NDC)

坐标系:

特点:

1.所有需要渲染到相机的图元都在这里面(或部分与之相交)
2.x,y,z属于[-1,1]。(如果有说z属于[0,1]的,那是老的或错的)
3.它就是MVP之后的结果。M(模型空间到世界空间)->V(世界空间到相机空间)->P(相机到投影空间,xyz已除w)->调整原点位置和坐标系大小(投影空间到NDC)

在NDC中,

我们屏幕上的每一个像素点,都是视线射线端点,射线方向朝正Z。视线端点充满了Z=-1,x,y属于[-1,1]的正方形。

可惜UE4材质函数没有直接提供从NDC到其他空间的转换。我嫌麻烦,那就还是和大多数算法一样,在相机空间中进行RayMarch,再转世界系。

3.相机空间

在相机空间中,

我们的相机位置成为射线端点,射线方向由相机指向nearClipPlane上的每一个像素采样中心

???这啥玩意儿,这我在其他RayTrace教程里咋每看见过?ShaderToy里也没见过?

没错,这个词是我发明的,但是存在的。我发现大部分光追教程和ShaderToy里的视线方向,都没涉及到相机的nearClipPlane和FOV。也就是说,他们大多数都是错的

以文首参考那篇ShaderToy为例,如果你大幅调整窗口长宽比,你会发现结果会变畸形,并偏移中心。ShaderToy窗口一般不会想着动,而且很多固定视角或只移动一点点,畸变不明显,无大碍。

一个典型的错误例子

当相机空间=世界空间,射线方向=normalize((2u-1)*ratio,2v-1,1)
ratio=屏幕分辨率x/屏幕分辨率y

我也不知道它咋推来的,可能和NDC搞混了,或者就是推错了。如果把1换成ratio,那么就正确了。

正确的推导

当水平FOV=90度:相机空间射线方向=normalize(2u-1,(2v-1)/ratio,1)
ratio=屏幕分辨率x/屏幕分辨率y

它是由最初推导简化来的:

当水平FOV=90度:相机空间射线方向=normalize((2u-1)*near,(2v-1)/ratio*near,near)

我们必须考虑屏幕上(u,v)点,对应空间里的屏幕(也就是nearClipPlane)中的哪个点,然后再与相机位置(0,0,0)相减得到视线方向。

当FOV确定为90度(UE4默认),那么我们可得maxX=near。

那么此视线向量就是(dx,dy,near)。

假设

又有当u=1,有

那么

所以

又当v=1,

那么

所以

所以

当水平FOV=90度:相机空间射线方向=normalize((2u-1)*near,(2v-1)/ratio*near,near)

FOV是个好东西,喜欢摄影一定要了解。

不过有一点,ue4中v坐标朝下,而相机系中y坐标朝上,要反一下,所以最终是

normalize((2u-1),-(2v-1)/ratio,1)

然后将射线方向转到世界空间,再March,就o了。

步骤

1.建立一个后期材质

float2 pos = -1.0 + 2.0 * uv;
float3 rayDir = normalize(float3(pos.x, -pos.y*Size.y/Size.x, 1));
return rayDir;
int i=0;
float3 nowPos;
float re=0;
for(i=0;i<RayDis;i++)
{nowPos = camPos+ RayStep*rayDir*i;if(length(nowPos)<100.0f){re+=GainStep;}
}
return re;

2.附加到后期体积的Material中。对于实际项目,需要通过Custom处理渲染顺序。

显然,如果我们将March的条件改成fbm或其他比较复杂的函数,能模拟很多不同的形状的云和雾。

结语

方法的方法还是比方法重要。

下节我们将在此基础上改进,并简单RayMarch出一个JuliaSet的形状。

Chango的数学Shader世界(十六)RayTrace三维分形(一)—— ue4中最简单的RayMarch相关推荐

  1. Chango的数学Shader世界(八)光盘模拟-各向异性,光栅衍射

    目的: 参考<GPU Gems>,在UE4中尝试以重现光盘Shader,并对书中的方法进行解析,改进,批评. 参考: <GPU Gems> 观察: 我越来越意识到观察现实的重要 ...

  2. Chango的数学Shader世界(九)流体模拟-散度,梯度,二阶导与拉普拉斯

    目的: 参考<GPU Gems>,在UE4中尝试重现2D流体模拟. 本节试图结合场论知识粗略理解Navier–Stokes equations. 参考: <GPU Gems> ...

  3. Chango的数学Shader世界(十四)细线间断,发光闪烁,TAA削弱处理

    目的: 减少游戏中的细线因屏幕分辨率不足和算法采样不足问题,导致的间断,以及相对的自发光闪烁.解决了此问题也附带解决了因TAA导致的细线自发光微弱的问题. 对比视频:https://www.bilib ...

  4. Chango的数学Shader世界(十五)油画Shader-技术分析,教程纠错

    目的: 实现油画后期Shader,探究教程中技术细节,指出错误. 参考: 搜索ue4 paint filter. UE4.21后整合自定义usf 观察: 油画的特点:成块的色块,但又保持清晰的边缘. ...

  5. Chango的数学Shader世界(七)水波模拟-透明水面,菲涅尔(Fresnel)效应

    目的: 解析,改进,批评一个国外免费透明水面Shader,进一步了解Shader背后的物理原理. 参考: 菲涅尔反射 分析: 我将原水面Shader一再简化,从中抽取最主要的部分,忽略细枝末节,并改掉 ...

  6. python进制转化bin oct dec hex_进制的英文表示法:BIN、OCT、HEX、DEC分别代表二、八、十六、十进制~BINOCTHEXDEC在英语中什么意思?...

    进制的英文表示法:BIN.OCT.HEX.DEC分别代表二.八.十六.十进制~ BIN_OCT_HEX_DEC_在英语中什么意思?,dec 容颜|用户:想咨询的 辰时数暖等屿凉.|用户:问问回答: b ...

  7. 星图识别题目及算法实现——数学建模(十六)

    天文导航中的星图识别 天体导航是基于已知的天体的坐标位置和运动规律.利用观测天体的天文坐标值确定导航体的空间位置等导航参数.与其他导航技术相比,天文导航是一种自主导航,不需要地面设备,不受人工或天然电 ...

  8. 【十六】 H.266/VVC | VVC中帧间预测技术详细总结 | 所有帧间预测技术代码汇总

    前言 ​ 帧间预测是影响视频编码性能的关键环节之一,H.266/VVC帧间预测在传统只能应对简单的平移运动的基础上,采用了仿射运动模型,可以描述更加复杂的缩放.旋转等运动.为了更好的发挥合并模式(Me ...

  9. (二十六)、Java数组在内存中如何存放与分配

    Java中有两种类型的数组: 基本数据类型数组: 对象数组: 当一个对象使用关键字"new"创建时,会在堆上分配内存空间,然后返回对象的引用,这对数组来说是一样的,因为数组也是一个 ...

  10. C语言试题三十六之将s所指字符串中所有下标为奇数位置上的字母转换为大写(若该位置上不是字母,则不转换)。

    1. 题目 请编写一个函数function,它的功能是:将s所指字符串中所有下标为奇数位置上的字母转换为大写(若该位置上不是字母,则不转换). 2 .温馨提示 C语言试题汇总里可用于计算机二级C语言笔 ...

最新文章

  1. 四川大学计算机学院2020推免公示,四川大学2020年推免生录取情况分析
  2. linux如何判断光盘是否挂载,LInux下如何挂载光盘找rpm包的方法步骤
  3. 计算机网络 | 网络基础 :网络协议,协议分层,数据封装与分用,地址管理,字节序
  4. json java对象 简书_Java 对象的 Json 化与反 Json 化
  5. 在IIS上部署你的ASP.NET Core项目
  6. react学习(50)--解决异步执行顺序问题
  7. NOI2004郁闷的出纳员
  8. 【开发者portal在线开发插件系列二】多条上下行消息(messageId的使用)
  9. Python监控Windows下的文件变化
  10. Convert Sorted Array to Binary Search Tree With Minimal Height
  11. SQLServer IP不能登录问题解决
  12. [转载] Python字符串的截取
  13. mvn install跳过测试
  14. 拓端tecdat|R语言JAGS贝叶斯回归模型分析博士生延期毕业完成论文时间
  15. java模拟安卓get请求,Java模拟HTTP Get Post请求实现论坛自动回帖功能
  16. 服务器清洗项目,服务器带电清洗流程和注意事项
  17. 游戏封包模拟器_问道模拟器人物移动封包分析教程
  18. python unmatched_Python
  19. 大数据管理技术 Hadoop-JavaAPI程序案例1
  20. [英语阅读]2010年内衣新宠:抗皱文胸

热门文章

  1. 透析极大极小搜索算法和α-β剪枝算法(有案例和完整代码)
  2. cad编辑节点快捷键是什么_CAD所有快捷键
  3. PID算法理解和代码以及PID调参
  4. 【2022PMP最全总结-敏捷专题课】
  5. sql server收缩数据库日志
  6. java如何动态添加数组数据_Java动态数组添加数据的方法与应用示例
  7. 用c51控制电机正反转以及加减速
  8. WO Mic -免费话筒
  9. 中国住户调查年鉴(2000-2021年)
  10. 常用z反变换公式表_高中三角函数公式推理amp;记忆