Chango的数学Shader世界(十七)RayTrace三维分形(二)—— Julia Set造型
目的:
移植Inigo Quilez的可视化三维Julia的算法到ue4。
本篇仅考虑造型,忽略表面法线计算和光照模型等。
忽略分形相关细节数学原理。
参考:
最近墙越来越高,我也没法放链接了。
1.Inigo Quilez在ShaderToy上的Julia,网址后缀MsfGRr
2.维度:数学漫步第一季的复数(下)
3.Ray Tracing Quaternion Julia Sets on the GPU——Keenan Crane,University of Illinois at Urbana-Champaign
pdf,非论文。
观察:
我们意识到难点有二:
1.完整的JuliaSet没有解析式,只有递推式。
若要判断某一点是否可由初始集合经过k次迭代能被包含,消耗也是巨大而不现实的。
因此我们似乎既没办法直接RayTrace,也没办法RayMarch出一个Julia云。
(下面是a=0时的2D情况,演示了2次迭代,这个特殊情况我们能判断点是否在Julia内,因为Julia此时为unit disk)
2.标准Julia集极其小,看不清。
由于是z^2+a,“可见部分”就跟单位圆差不多大小。我们希望搞一个actor,能随意缩放,位移Julia。但又不改变Julia的那些公式(因为理论公式现成,要改麻烦)。
分析:
1.问题一:根据距离场RayMarch到Julia表面
简而言之,虽无Julia表面解析式,但有其距离场估计的表达式。
距离场是一个数值场S=F(x,y,z),空间中每点数值为距离Julia表面最近的距离。
伪代码
bool intersectJulia(...)
{float h = 1.0;float t = 0.0;for( int i=0; i<最大March次数; i++ ){if( h<0.0001(碰到表面) ||t>最远距离 (没有碰到表面) ){break;}h = MarchStep( ro+rd*t, ...);t += h;}if( t<最远距离) { return true; }return false;
}
2.问题二:移动ro位置
Julia所有表达式不变,对传入的视线射线的端点位置调整。
ro本来是相机位置camPos。
缩放:对camPos缩放,越小,说明我们越接近单位圆去ray这个Julia,Julia越大。
移动:camPos-JuliaPos
步骤
1.计算ro
注意到RayMarchFunc也被连了进去。它以*1的形式参与ro的计算,而主函数以ro为参,保证了其usf内的函数先于主函数编译。
//RayMarchFunc.usfreturn 1;
}float4 qsqr( float4 a ) // square a quaterion
{return float4( a.x*a.x - a.y*a.y - a.z*a.z - a.w*a.w,2.0*a.x*a.y,2.0*a.x*a.z,2.0*a.x*a.w );
}float map(float3 p,float4 c )
{float4 z = float4(p,0.0);float md2 = 1.0;float mz2 = dot(z,z);float4 trap = float4(abs(z.xyz),dot(z,z));float n = 1.0;for( int i=0; i<11; i++ ){// dz -> 2·z·dz, meaning |dz| -> 2·|z|·|dz|// Now we take thr 2.0 out of the loop and do it at the end with an exp2md2 *= mz2;// z -> z^2 + cz = qsqr(z) + c; trap = min( trap, float4(abs(z.xyz),dot(z,z)) );mz2 = dot(z,z);if(mz2>4.0) break;n += 1.0;}return 0.25*sqrt(mz2/md2)*exp2(-n)*log(mz2); // d = 0.5·|z|·log|z| / |dz|
}bool intersectJulia(float3 ro, float3 rd ,float4 c)
{float4 res;float resT = -1.0;float maxd = 10.0;float h = 1.0;float t = 0.0;for( int i=0; i<300; i++ ){if( h<0.0001||t>maxd ) break;h = map( ro+rd*t, c );t += h;}if( t<maxd ) { resT=t;return true; }return false;
2.计算rd
和上篇一样
3.主函数
其中c就是julia递推式z^2+a的a。
4.结合蓝图Actor
控制材质参数,包括Julia位置等。
5.结果
在ue4默认相机下,正常工作。
我注意到,当我使用ue4影视镜头时,由于其FOV并非90度,所以移动起来Julia的位置和大小不正常。这和上面的推导一致。
我还把Inigo Quilez计算法线的部分移植进来。这部分代码对我来说水平太高且不具普遍性,放弃理解了。先只写了一个diffuse,看起来不是很好看。对比最近的分形宣传视频,果然分形好看还是在光照和材质上。
当然,IQ大神自己是能信手拈来好看的光照模型的,并且作了AA。这是shaderToy原图:
但他的代码太过硬核,不适合学习。所以我决定找找其他代码清晰,而各方面都考虑得比较全面得Shader学习一下。
这是他的光照部分的代码:
// sky
{
float co = clamp( dot(-rd,nor), 0.0, 1.0 );
vec3 ref = reflect( rd, nor );
//float sha = softshadow( pos+0.0005*nor, ref, 0.001, 4.0, c );
float sha = occ;
sha *= smoothstep( -0.1, 0.1, ref.y );
float fre = 0.1 + 0.9*pow(1.0-co,5.0);col = mate*0.3*vec3(0.8,0.9,1.0)*(0.6+0.4*nor.y)*occ;
col += 2.0*0.3*vec3(0.8,0.9,1.0)*(0.6+0.4*nor.y)*sha*fre;
}// sun
{
const vec3 lig = sun;
float dif = clamp( dot( lig, nor ), 0.0, 1.0 );
float sha = softshadow( pos, lig, 0.001, 64.0, c );
vec3 hal = normalize( -rd+lig );
float co = clamp( dot(hal,lig), 0.0, 1.0 );
float fre = 0.04 + 0.96*pow(1.0-co,5.0);
float spe = pow(clamp(dot(hal,nor), 0.0, 1.0 ), 32.0 );
col += mate*3.5*vec3(1.00,0.90,0.70)*dif*sha;
col += 7.0*3.5*vec3(1.00,0.90,0.70)*spe*dif*sha*fre;
}// extra fill
{
const vec3 lig = vec3( -0.707, 0.000, -0.707 );
float dif = clamp(0.5+0.5*dot(lig,nor), 0.0, 1.0 );
col += mate* 1.5*vec3(0.14,0.14,0.14)*dif*occ;
}// fake SSS
{
float fre = clamp( 1.+dot(rd,nor), 0.0, 1.0 );
col += mate* mate*0.6*fre*fre*(0.2+0.8*occ);
}
结语
之后参考比较规整的光照模型,将Julia Set表面整好看点...
1.技术差,就会丑。
2.在非学术的Shader实现里,我经常看到Inigo Quilez。我最佩服的就是他独立思考的能力。以参考中的那篇ShaderToy所附带的技术博客为例,他抛开常见的z=a+bi+cj+dk形式的复数,自创z=a+bi+cj形式复数,并规定基向量的运算规则,十分大胆。针对实际问题,更改思考框架的操作可以说是我的梦想。
3.在Ray Tracing Quaternion Julia Sets on the GPU中,作者十分风趣,各个细节都十分详细(就像把你当傻瓜一样),甚至充满半页纸的图,结尾直接上代码,你不理解都不行。与满篇废话又不着重点,吹上天又没东西的gp论文比,我太喜欢了。
作者的伊利诺伊大学厄巴纳-香槟分校似乎挺牛的。
Chango的数学Shader世界(十七)RayTrace三维分形(二)—— Julia Set造型相关推荐
- Chango的数学Shader世界(十四)细线间断,发光闪烁,TAA削弱处理
目的: 减少游戏中的细线因屏幕分辨率不足和算法采样不足问题,导致的间断,以及相对的自发光闪烁.解决了此问题也附带解决了因TAA导致的细线自发光微弱的问题. 对比视频:https://www.bilib ...
- Chango的数学Shader世界(八)光盘模拟-各向异性,光栅衍射
目的: 参考<GPU Gems>,在UE4中尝试以重现光盘Shader,并对书中的方法进行解析,改进,批评. 参考: <GPU Gems> 观察: 我越来越意识到观察现实的重要 ...
- Chango的数学Shader世界(十五)油画Shader-技术分析,教程纠错
目的: 实现油画后期Shader,探究教程中技术细节,指出错误. 参考: 搜索ue4 paint filter. UE4.21后整合自定义usf 观察: 油画的特点:成块的色块,但又保持清晰的边缘. ...
- Chango的数学Shader世界(七)水波模拟-透明水面,菲涅尔(Fresnel)效应
目的: 解析,改进,批评一个国外免费透明水面Shader,进一步了解Shader背后的物理原理. 参考: 菲涅尔反射 分析: 我将原水面Shader一再简化,从中抽取最主要的部分,忽略细枝末节,并改掉 ...
- Chango的数学Shader世界(九)流体模拟-散度,梯度,二阶导与拉普拉斯
目的: 参考<GPU Gems>,在UE4中尝试重现2D流体模拟. 本节试图结合场论知识粗略理解Navier–Stokes equations. 参考: <GPU Gems> ...
- 【Visual C++】游戏开发笔记四十三 浅墨DirectX教程十一 为三维世界添彩:纹理映射技术(二)...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 作者:毛星云(浅墨) 邮箱: happylifemxy@163.com 本篇文章里,我们首先对Direct3D之中固定功能流水线中的 ...
- 吴文俊: 中国古代数学对世界文化的伟大贡献
公元前221年, 秦始皇灭六国, 建立了中国历史上第一个中央集权的封建国家. 汉承秦制, 自秦至西汉中期这两百来年间, 是新兴地主阶级专政巩固发展与上升的时期, 法家路线占着主导地位. 法家对工农业生 ...
- 为什么要深入数学的世界
为什么要深入数学的世界 作为计算机的学生,我没有任何企图要成为一个数学家.我学习数学的目的,是要 想爬上巨人的肩膀,希望站在更高的高度,能把我自己研究的东西看得更深广一些.说起来,我在刚来这个学校的时 ...
- 【数学建模】基于matlab三维海浪模型仿真【含Matlab源码 1159期】
一.获取代码方式 获取代码方式1: 完整代码已上传我的资源:[数学建模]基于matlab三维海浪模型仿真[含Matlab源码 1159期] 点击上面蓝色字体,直接付费下载,即可. 获取代码方式2: 付 ...
- 为什么要深入数学的世界?
在过去的一年中,我一直在数学的海洋中游荡,research(研究)进展不多,对于数学世界的阅历算是有了一些长进. 为什么要深入数学的世界? 作为计算机的学生,我没有任何企图要成为一个数学家.我学习数学 ...
最新文章
- linux 中的who的参数,linux who命令参数及用法详解
- vijos 1512 SuperBrother打鼹鼠
- Delphi自动提交网页表单和获取框架网页源码
- MySQL高级 - 常用工具 - mysqlbinlog与mysqldump
- 非线性动力学_非线性动力学特辑 低维到高维的联通者
- java并发编程-----深入剖析ThreadLocal
- weka分类器怎么设置样本类别_NeurIPS 2020 | 自步对比学习: 充分挖掘无监督学习样本...
- 谷歌提出“数据回波”榨干GPU空闲时间,训练速度提升3倍多
- VLD在VS2019中的使用以及应用程序无法正常启动(0xc0150002)
- java pdf 使用itextpdf插入页码
- sketch导出html可以跳转,Sketch导入、导出功能说明及技巧
- open judge 1.8.1
- 单细胞论文记录(part7)--DL and alignment of spatially resolved single-cell transcriptomes with Tangram
- 解读CUDA Compiler Driver NVCC - Ch.3
- kibana笔记 -- KQL
- 程序员的自我修养,不断提升认知,赚他个1000万不香吗?
- 为什么我认识的机械工程师都抱怨工资低?
- 计算机与计算机网络_让计算机承担责任
- 安卓电子书格式_[技巧] 无敌的boss级电子书阅读app,全能高手就要一个打十个。...
- 基于HTML节日主题网页项目的设计与实现——圣诞节日介绍(HTML+CSS)