Analytic Normals 3D代码解析_vec2 ibox( in vec3 ro, in vec3 rd, in vec3 rad ) v-程序员宅基地

技术标签: 3d渲染  ShaderToy  计算机图形学  

Analytic Normals 3D代码解析

作者:iq,网址:https://www.shadertoy.com/view/XttSz2

标签:3d, noise, normals, analytical, numerical

总共一个部分:Image

照相机设置

这个比较常见,就是简单的照相机旋转和矩阵获取

// camera anim
float an = 0.1*iTime;
vec3 ro = 3.0*vec3( cos(an), 0.8, sin(an) );
vec3 ta = vec3( 0.0 );
// camera matrix	
vec3  cw = normalize( ta-ro );
vec3  cu = normalize( cross(cw,vec3(0.0,1.0,0.0)) );
vec3  cv = normalize( cross(cu,cw) );
vec3  rd = normalize( p.x*cu + p.y*cv + 1.7*cw );

相交测试函数

之后是进行相交测试

vec4 interesect( in vec3 ro, in vec3 rd )
{
	vec4 res = vec4(-1.0);

    // 正方形相交测试   
    vec2 dis = iBox( ro, rd, vec3(1.5) ) ;
    if( dis.y<0.0 ) return res;

    // raymarch
    float tmax = dis.y;
    float t = dis.x;
	for( int i=0; i<128; i++ )
	{
        vec3 pos = ro + t*rd;
		vec4 hnor = map( pos );
        res = vec4(t,hnor.yzw);
        
		if( hnor.x<0.001 ) break;
		t += hnor.x;
        if( t>tmax ) break;
	}

	if( t>tmax ) res = vec4(-1.0);
	return res;
}

首先是判断射线与正方形是否相交,如果相交,返回两个交点。具体关于相交测试函数,可以参考IQ的博客。然后在两个交点产生的[tmin,tmax]的范围内进行RayMarching, 核心是Map函数,如下所示:

vec4 map( in vec3 p )
{
	vec4 d1 = fbmd( p );
    d1.x -= 0.37;
	d1.x *= 0.7;
    d1.yzw = normalize(d1.yzw);
    // clip to box
    vec4 d2 = sdBox( p, vec3(1.5) );
    return (d1.x>d2.x) ? d1 : d2;
}

具体分析:对于d1,是通过分数布朗函数获得随机点(其中,x分量是t,yzw是法线),这里和之前了解到的FBM函数的区别在于,得到了随机点的法向量。当然我们也可以直接使用常规的calNormal函数。对于结果,进行了区间重映射。为什么需要这个重映射呢(一次加减法,一次乘法)?其核心是加减法,乘法是无所谓的(效果上也是这样表现的),试想,如果我们不减去一个值,那么FBM的返回值始终是大于0的,那么无论怎么往前推进(在FMB上,表现是在曲面上移动),都不会结束,在效果表现上,如果删去这行,则所有射线都会投到无限远处,而不断增大减去的值,几何体越接近完整的正方形。

然后在判断离正方形的距离,两个结果相比较,返回较大值的结果和法向量。回到interesect函数,之后是常规的射线步进操作。最后返回主函数。

渲染过程

首先计算AO。使用球面斐波那契采样(实际是半球)得到均匀的采样,采样32次,每次进行map,累加返回结果的步进距离,然后除以32,这里有个问题——在进行Clamp的时候,分别乘以3,5。这里的分析:因为我们对于采样点的判断是它离几何体的距离,而不是灯光方向的深度图,所以,哪怕对于正方体表面的点,对其进行采样,它们的返回值依然不会很大,所以需要乘上倍数。

float calcAO( in vec3 pos, in vec3 nor )
{
    
	float ao = 0.0;
    for( int i=0; i<32; i++ )
    {
    
        //球面斐波那契均匀采样
        vec3 ap = forwardSF( float(i), 32.0 );
        //随机值
        float h = hash(float(i));
        //反法线方向半球倒转方向
		ap *= sign( dot(ap,nor) ) * h*0.25;
        ao += clamp( map( pos + nor*0.001 + ap ).x*3.0, 0.0, 1.0 );
    }
	ao /= 32.0;
	
    return clamp( ao*5.0, 0.0, 1.0 );
}

然后计算Fre,Fro。

float fre = clamp( 1.0+dot(rd,nor), 0.0, 1.0 );
float fro = clamp( dot(nor,-rd), 0.0, 1.0 );

其中,Fre是菲尼尔效应的近似,大致如图:在图中,越平坦,紫色段越短,那么1减去紫色段的值越大,那么菲涅尔效应越强。Fro则相反,或者说接近一般的计算。

然后正式计算颜色

col = mix( vec3(0.05,0.2,0.3), vec3(1.0,0.95,0.85), 0.5+0.5*nor.y );
//col = 0.5+0.5*nor;
col += 10.0*pow(fro,12.0)*(0.04+0.96*pow(fre,5.0));
col *= pow(vec3(occ),vec3(1.0,1.1,1.1) );

第一行:计算基本的颜色,因人而异,这里是将颜色和法线的Y分量挂钩(正相关)。第二行,使用计算好的fre,fro。具体含义不知,以后有机会搞明白。第三行,加入AO。

最后,转为伽马空间后,结束。

*工具iBox函数

vec2 iBox( in vec3 ro, in vec3 rd, in vec3 rad ) 
{
    vec3 m = 1.0/rd;
    vec3 n = m*ro;
    vec3 k = abs(m)*rad;
    vec3 t1 = -n - k;
    vec3 t2 = -n + k;
	float tN = max( max( t1.x, t1.y ), t1.z );
	float tF = min( min( t2.x, t2.y ), t2.z );
	if( tN > tF || tF < 0.0) return vec2(-1.0);
	return vec2( tN, tF );
}

*工具FBMD函数

vec4 fbmd( in vec3 x )
{
    const float scale  = 1.5;

    float a = 0.0;
    float b = 0.5;
	float f = 1.0;
    vec3  d = vec3(0.0);
    for( int i=0; i<8; i++ )
    {
        vec4 n = noised(f*x*scale);
        a += b*n.x;           // accumulate values		
        d += b*n.yzw*f*scale; // accumulate derivatives
        b *= 0.5;             // amplitude decrease
        f *= 1.8;             // frequency increase
    }
	return vec4( a, d );
}

*工具SdBox函数

vec4 sdBox( vec3 p, vec3 b ) // distance and normal
{
    vec3 d = abs(p) - b;
    float x = min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
    vec3  n = step(d.yzx,d.xyz)*step(d.zxy,d.xyz)*sign(p);
    return vec4( x, n );
}

*工具ValueNoise及其梯度

float hash( float n ) { return fract(sin(n)*753.5453123); }
vec4 noised( in vec3 x )
{
    vec3 p = floor(x);
    vec3 w = fract(x);
	vec3 u = w*w*(3.0-2.0*w);
    vec3 du = 6.0*w*(1.0-w);
    
    float n = p.x + p.y*157.0 + 113.0*p.z;
    
    float a = hash(n+  0.0);
    float b = hash(n+  1.0);
    float c = hash(n+157.0);
    float d = hash(n+158.0);
    float e = hash(n+113.0);
	float f = hash(n+114.0);
    float g = hash(n+270.0);
    float h = hash(n+271.0);
	
    float k0 =   a;
    float k1 =   b - a;
    float k2 =   c - a;
    float k3 =   e - a;
    float k4 =   a - b - c + d;
    float k5 =   a - c - e + g;
    float k6 =   a - b - e + f;
    float k7 = - a + b + c - d + e - f - g + h;

    return vec4( k0 + k1*u.x + k2*u.y + k3*u.z + k4*u.x*u.y + k5*u.y*u.z + k6*u.z*u.x + k7*u.x*u.y*u.z, 
                 du * (vec3(k1,k2,k3) + u.yzx*vec3(k4,k5,k6) + u.zxy*vec3(k6,k4,k5) + k7*u.yzx*u.zxy ));
}
return vec4( k0 + k1*u.x + k2*u.y + k3*u.z + k4*u.x*u.y + k5*u.y*u.z + k6*u.z*u.x + k7*u.x*u.y*u.z, 
             du * (vec3(k1,k2,k3) + u.yzx*vec3(k4,k5,k6) + u.zxy*vec3(k6,k4,k5) + k7*u.yzx*u.zxy ));

}




### *工具ForwardSF函数
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/JMXIN422/article/details/117808127

智能推荐

关于AI芯片功耗和应用的一些看法-程序员宅基地

文章浏览阅读1.3k次。来源:内容来自知乎专栏ARM杂谈,作者重走此间路,谢谢。近一年各种深度学习平台和硬件层出不穷,各种xPU的功耗和面积数据也是满天飞,感觉有点乱。在这里我把我看到的一点情况做一些小结,顺便列一下可能的市场。在展开之前,我想强调的是,深度学习的应用无数,我能看到的只有能在千万级以上的设备中部署的市场,各个小众市场并不在列。深度学习目前最能落地的应用有两个方向,一个是图像识别,一个是语音识别。这...

如何将STM32CubeMX + TouchGFX 工程中生成的图片,字库等超大数组保存到QSPI FLASH (W25Q256)_keil如何将图片存入qspi flash-程序员宅基地

文章浏览阅读1w次,点赞7次,收藏62次。(本人业余时间接相关外包,欢迎联系!)软件环境:STM32CubeMX5.3 、TouchGFX 4.10.0Designer、uVision5.28.0.0硬件环境:正点原子阿波罗STM32F767开发板、4.3寸LCD接口屏(480×272)、W25Q256本博客源码链接(GitHub):https://github.com/ningjw/stm32f7_os/tree/016..._keil如何将图片存入qspi flash

【第三部分 | 移动端开发】1:移动端基础概要-程序员宅基地

文章浏览阅读332次。介绍了一下移动端开发的基本知识

Windows 10使用Qt配置OpenCV时出现的一些编译错误小记_windows bindings opencv_python3 编译异常-程序员宅基地

文章浏览阅读2.9k次,点赞5次,收藏16次。Windows 10使用Qt配置OpenCV时出现的一些编译错误の解决方案开始安装功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入本人是Qt以及OpenCV新手,使用Windows版本的Qt配置OpenCV,因为需要自己编译,遇_windows bindings opencv_python3 编译异常

计算机新生导论感言,新生入学感言范文精选-程序员宅基地

文章浏览阅读252次。【导语】即将应对新环境,新老师,新同学,新课本,我在感到欣喜的同时又感到繁重的压力和紧张。即将离开父母,我十分不舍,从小到大都是在父母的怀抱中长大的,父母会为自己铺好道路,尽量去减少自己人生路上的绊脚石。无忧考网为大家整理的《新生入学感言范文精选》,希望对大家有所帮助!篇一  告别了中学时代,我满怀期望的进入大学的校门,我的大学生活开始了。我们从八方走来,相识相聚在外这个大家庭。在那里我认识了我将..._即将离开父母,我十分不舍,从小到大都是在父母的怀抱中长大的,父母会为自己铺好道

疫苗条形码:条形码技术如何使药剂师受益-程序员宅基地

文章浏览阅读1.4k次,点赞27次,收藏21次。在制药领域,条形码技术提供了多种优势,从有效的库存管理到快速定位过期的药品容器。使用强大的条形码扫描解决方案有助于简化工作流程、提高员工生产力并确保患者安全。

随便推点

探索数学之美:Prathyvsh 的 Category Theory Resources-程序员宅基地

文章浏览阅读287次,点赞5次,收藏4次。探索数学之美:Prathyvsh 的 Category Theory Resources项目地址:https://gitcode.com/prathyvsh/category-theory-resources项目简介Category Theory Resources 是一个由 Prathyvsh 创建并维护的开源项目,旨在为学习和研究范畴论(Category Theory)的程序员、数学爱好...

Twisted: 强大的Python异步网络编程框架-程序员宅基地

文章浏览阅读390次,点赞3次,收藏9次。Twisted: 强大的Python异步网络编程框架Twisted是一个开源的Python网络应用框架,用于开发高性能、可扩展的网络应用程序。它是基于事件驱动的非阻塞I/O模型,支持多种协议,如TCP、UDP、HTTP、SMTP等。Twisted可以用来做什么?开发并发服务器程序:通过异步处理网络请求,能够有效提高服务器性能。创建复杂的网络应用:Twisted提供了丰富的API,可以帮..._twisted框架用来做什么

基于stm32F103C8的集尘风机电源设计-程序员宅基地

文章浏览阅读75次。本文从设计原理、硬件设计、软件设计、性能测试等方面细致分析了该电源板的设计要点和优势点,以期为工业领域的集尘设备设计提供更多的技术支持和参考。整个电路板采用6层设计,其中第一层为元器件层,第二层为地电位面,第三层为电源数位,第四层为地电位平面,第五层为PWM层,第六层为电源信号数字地面等。本文将介绍一种基于STM32F103C8的集尘风机电源设计,这篇文章将围绕如下主题展开:设计原理、硬件设计、软件设计、性能测试以及总结。测试结果表明,该电源板具有极高的实用性和稳定性,可以满足工业领域的高效集尘需求。

一款Mac系统NTFS磁盘读写软件Tuxera NTFS 2023 for Mac-程序员宅基地

文章浏览阅读1k次,点赞24次,收藏8次。设置成功之后,点击屏幕左上角的苹果标志重启电脑,重启之后运行软件,屏幕上会跳出“系统扩展已被阻止”窗口,点击【打开安全性偏好设置】,在出现的安全性与隐私窗口中,首先点击左下角的小锁进行解锁,然后再点击【允许】,按照提示进行重新启动即可。2、安装之前,会有个提示:此软件包将运行一个程序以确定该软件能否安装,点击【允许】,然后安装向导就会出现,在出现的介绍中,我们可以观察到这款读写软件所包含的组件,点击【继续】;3、当然在软件的安装过程中,当进行到“产品密钥”这一步时,同样也可以通过同样的操作激活软件。

20201217网警考试题目及题目源码(百度云网盘下载链接)-程序员宅基地

文章浏览阅读2.4k次。20201217网警考试题目及题目源码(百度云网盘下载链接)解题答案视频教程请关注"极客易先生"微信公众号链接:https://pan.baidu.com/s/1pzimgPk_fRmgYHdM0BBQBg提取码:iex6本题目由极客易先生收集整理,全套解题视频教程学习请上www.hk007.cn跟极客易先生学开发渗透课,就上www.hk007.cn19、被嫌疑人盗取拖动的网站源码压缩文件的SHA-1值为:(格式:345ADEE)8F8319BC3C1B8ED92AA5498DD98C.._网警考试

为什么卷积要翻转/为什么深度学习卷积不翻转/卷积和相关_卷积为什么要翻转-程序员宅基地

文章浏览阅读5k次,点赞4次,收藏23次。所以究其原因,是因为“时间的相对”,x(t’)过去1秒后,对“现在t"的影响力度是h(1);x(t’’)过去2秒后,对“现在t"的影响力度是h(2);…站在现在时刻t,向左看,看到的是h(3),h(2),h(1),h(0),倒过来的参考..._卷积为什么要翻转

推荐文章

热门文章

相关标签