使用shadergraph实现虚拟室内效果
前言
之前在看网页的时候发现有一篇虚拟室内效果的教程 ,于是就在Unity中使用ShaderGraph来实现了一遍,具体思路与教程中一直,只不过在shadergraph中有些地方需要注意一下。
正文
1、单面的映射
cubemap uv
对于cubemap的颜色采样,我们需要将起视为一个三维物体,而不是一个平面,在unity shadergraph中,对于cubemap的采用是从中心点,开始,如图坐标中心。因此对于cubemap的采用不是简单的从边缘获取坐标,而是回去计算边缘点到中心的一个向量,这个向量也可以看成cubemap的uv。
因为这样,在shadergraph的cubemap sample节点中,没有uv这一个solt而是一个viewdir solt。因此只需要把我们计算得到的向量放到viewdir的接口处即可。
已知相机位置与相机视角方向、平面的一个点,与平面的法线,能够求得射线与平面的交点。p‘
这个交点p’如果转成cubemap的坐标就能实现虚拟室内的效果
交点p’公式如下:
P
0
=
l
+
t
l
⃗
P_{0}=l+t\vec{l}
P0=l+tl
t
=
(
(
l
−
p
)
⋅
n
⃗
)
l
⃗
−
n
⃗
t=\frac{((l-p)\cdot \vec{n})}{\vec{l}-\vec{n}}
t=l−n((l−p)⋅n)
求出之后,在cubemap上进行采样就能获取到对应的颜色值。求出P点之后,有一个需要注意的是,我们要求出cubemap的采样,首先需要获取该点在cubemap uv空间的坐标值。由图形学已知,cubemap的采样是从中心点出发,因此我们可以理解为,知道一个点的世界坐标,然后减去cubemap的中心点的世界坐标,就能求出在模型空间中的向量。这个向量就是我们所需要的uv坐标。
算法的shadergraph实现就不放图了,可以作为练手自己尝试实现,可以与我的git项目进行参考。
2、遮罩的设置
有的单面映射但是因为采样的范围是无限远,因此还会出现边缘扭曲的效果,因此需要加上遮罩。
当uv取值大于设定值之后,在设置repeat的纹理就会向外延申。
遮罩算法
以一个平面为例,在虚拟正方体内部的顶点的范围在[-5,5]之间,在之外的点的绝对值下x,y,z三个值总会有一个大,因此遮罩算法的思路就是将[-5,5]缩小到[-1,1],然后将外面大的就减掉。
[-5,5]-》[-1,1]
上图我标记了4个步骤:
第一步,将所有的虚拟坐标除5,这样[-5,5]这个范围内的值,就缩小到了[-1,1]
第二步,将所有的值取绝对值,并向下取整,这样[-1,1]就缩小到[0,0]
第三步,将值与1进行比较,然后将超出1范围内的值清零,0则扩大到1,这样就提取出虚拟正方体一个面的具体坐标值。
第四步,将坐标扩展值三维空间,为后面遮罩计算做好准备(如果不扩展,shadergraph会给一个默认值,这个默认值可能不正确
效果
3、5面叠加
有了一面的结果之后,就可以准备复制叠加
shadergraph节点
在复制的过程中需要注意,由于每一个面片所对应的平面不同,因此修改修改遮罩算法中的判断函数的输入。
如果平面是平行于x0y平面,那么这里max节点的输入应该是r,g,因为在这个平面中人r,g两个值是在改变的,如果平行于xoz平面,那么max节点的输入应该是r,b。
最后将每一个分支使用add节点叠加,出效果。
Project link:
source code
有更好的实现,可以通过我的邮箱联系我,一起讨论。
站在巨人的肩膀上!