高级纹理映射
立方体纹理
立方体纹理是环境映射的一种实现方法。立方体纹理就是将沿着世界空间下观察得到的上下左右前后六个方向的图像存储在立方体的六个面上。它可以实现反射和折射的效果。
可以通过3D方向矢量对立方体纹理进行采样,从立方体中心出发,沿着矢量方向延伸就可以和立方体的六个纹理之一发生相交,交点就是需要采样的纹理。
天空盒子
天空盒子用于模拟背景。它是一个盒子,使用skybox时,整个场景被包围在一个立方体内。立方体的每个面使用立方体纹理映射技术。
- 创建一个材质,并选择skybox/6 sided,并将六张纹理图赋值给材质,将纹理的WrapMode设置为Clamp,防止在接缝处出现不匹配。
- 将材质赋给摄像机,或者在Lighting中将材质赋值给Skybox选项(这个方法会将所有摄像机的skybox设置为同一个).
第三种方法创建立方体纹理的步骤如下:
- 准备好程序脚本。
- 创建一个空的GameObject,将以这个GameObject的位置信息来渲染立方体纹理。
- 创建一个Cubemap用于存储立方体纹理,并将Readable勾选。
- 使用脚本将以GameObject为中心观察到的世界空间下的6张图渲染到立方体纹理中。
反射 使用立方体纹理使得物体具有反射效果。如图,就像镀了一层金属。
文章图片
步骤如下:
- 调整模型的位置,将其与生成立方体纹理的GameObject的位置一样。然后将立方体人纹理赋给模型。
- 给Shader 的 properties添加属性_Cubemap(类型为Cube)
- 在顶点着色器中用reflect函数获得物体的反射方向o.worldRefl = reflect(-o.worldViewDir,o.worldNormal);
- 在片元着色器中利用反射方向对立方体纹理_Cubemap进行采样。fixed3 reflection = texCUBE(_Cubemap,i.worldRefl).rgb * _ReflectColor.rgb;
- 最后将反射颜色和漫反射颜色线性混合并和环境光相加后返回。
步骤如下:
- 调整模型的位置,并赋给材质。
- 在Shader中声明透射比和立方体纹理
- 在 顶点着色器中计算折射方向,需要将入射光线和表面法线归一化。o.worldRefl = refract(-normalize(o.worldViewDir),normalize(o.worldNormal),_RefractRatio);
- 在片元着色器中利用折射方向对立方体纹理进行采样。fixed3 reflection = texCUBE(_Cubemap,i.worldRefl).rgb * _RefractColor.rgb;
- 混合漫反射颜色和折射颜色并和环境光相加后返回。
菲涅尔反射与视角方向有关,近似等式为:F(v,n)=F0+(1-F0)(1-v*n)^5。F0是反射系数。
步骤如下:
- 调整模型的位置,并赋给材质。
- 在Shader中声明菲涅尔反射系数和立方体纹理。
- 在顶点着色器中计算反射方向。o.worldRefl = reflect(-o.worldViewDir,o.worldNormal);
- 在片元着色器中计算菲涅尔反射。fixed fresnel = _FresnelScale + (1 - _FresnelScale)*pow(1-dot(worldViewDir,worldNormal),5);
- 利用菲涅尔反射混合漫反射和反射颜色。fixed3 color = ambient + (lerp(diffuse,reflection,saturate(fresnel))+specular)*atten;
【高级纹理映射】渲染纹理就是利用一个摄像机,将其看到的图像渲染到一个中间缓冲中 ,这个中间缓冲就是渲染目标纹理。利用渲染纹理,我们可以实现镜子效果,和玻璃效果。
镜子效果 步骤如下:
- 创建一个材质。
- 创建一个立方体将其作为镜子,并调整其位置和大小,将第一步创建的材质赋值给它。
- 创建一个渲染纹理(create,render texture)
- 创建一个摄像机,调整其位置,裁剪平面,视角等,然后将摄像机看到的图像渲染到渲染纹理(将第三部创建的渲染纹理拖拽到摄像机的target texture上)。
- 在shader的顶点着色器中翻转纹理坐标的水平坐标,对渲染纹理进行采样。
玻璃效果 除了使用一个额外的摄像机获取屏幕图像,还可以在unity shader中定义一个GrabPass,然后unity会将当前屏幕的图像绘制在一张纹理中供我们在后续的pass中访问。GrabPass可以用来模拟透明材质,但是与简单的使用透明混合不同,其可以对物体后面的图像进行更复杂的处理。但是要额外小心渲染队列设置,将其设置为Transparent,保证所有不透明物体先被渲染。
步骤如下:
- 在shader的properties中定义玻璃的材质纹理,法线纹理,立方体纹理等。
- 在SubShader中定义GrabPass。GrabPass {"_RefractionTex"}。unity会将当前屏幕图像绘制在_RefractionTex中,供后续Pass访问。
- 在Pass中定义_RefractionTex和_RefractionTex_TexelSize变量,_RefractionTex_TexelSize是文素大小。
- 在顶点着色器中获取顶点的屏幕坐标,o.scrPos = ComputeGrabScreenPos(o.pos);
- 在片元着色器中利用法线等信息计算偏移量,然后用偏移量对屏幕图像_RefractionTex进行采样,以此来模拟折射效果。
fixed2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy; i.scrPos.xy = offset + i.scrPos.xy; fixed3 refrCol = tex2D(_RefractionTex,i.scrPos.xy/i.scrPos.w).rgb;
总的来说,这个方法就是,利用反射那一节的 方法来计算物体表面的反射颜色,然后利用GrabPass获取到的屏幕图像,对其采样来模拟折射(采样坐标经过了偏移,这样得到的纹理看上去就像扭曲了一样),得到折射颜色,最后将反射和折射颜色混合。
文章图片
程序纹理
程序纹理就是利用c#脚本来生成纹理图像。
推荐阅读
- 唐嫣可真会穿,西装搭牛仔裤都能穿出高级感,一双大长腿太抢镜
- 鹿鸣高级营养老师徐老师分享应该注意的6种食物
- Java基础-高级特性-枚举实现状态机
- HTTP高级(Cookie,Session|HTTP高级(Cookie,Session ,LocalStorage )
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- 十一、理解纹理坐标
- Kotlin泛型的高级特性(六)
- Swift高级应用|Swift高级应用 -01
- 你也可以拍出高级感的照片
- 前端|web前端dya07--ES6高级语法的转化&render&vue与webpack&export