Unity3D ShaderLab立方体图的法线渲染

 

某些情况下,我们希望立方体图的材质球上产生法线效果,来更多的表现细节,比如菱形花纹的玻璃,冰块的表面。

在帧数的协调下,我们可以通过input结构体的另一个内置参数来传递我们的法线贴图。下面 我们就一步步实现。

首先,新建Shader,在新建材质球,准备立方体图,法线贴图。双击shader进入脚本编辑。

本次的代码修改依然是和之前的立方体图的反射遮罩差不多,所以就直接看完成的代码吧。

 

code start ---------------------------------------------------------------------

 

 

Shader "91YGame/ReflectionNormal" {

Properties {

_MainTint("Diffuse Tint",Color)=(1,1,1,1)

_MainTex ("Base (RGB)", 2D) = "white" {}

_NormalMap("Normal Map",2D)=""{}

_CubeMap("CubeMap",CUBE)=""{}

_ReflAmount("Reflection Amount",Range(0.1,3))=0.5

}

SubShader {

Tags { "RenderType"="Opaque" }

LOD 200

 

CGPROGRAM

#pragma surface surf Lambert

 

sampler2D _MainTex;

sampler2D _NormalMap;

samplerCUBE _CubeMap;

float4 _MainTint;

float _ReflAmount;

 

struct Input {

float2 uv_MainTex;

float2 uv_NormalMap;

float3 worldRefl;

INTERNAL_DATA

};

 

void surf (Input IN, inout SurfaceOutput o) {

half4 c = tex2D (_MainTex, IN.uv_MainTex);

float3 normals = UnpackNormal(tex2D(_NormalMap,IN.uv_NormalMap)).rgb;

o.Normal = normals;

o.Emission=texCUBE(_CubeMap,WorldReflectionVector(IN,o.Normal) ).rgb*_ReflAmount;

o.Albedo = c.rgb*_MainTint;

o.Alpha = c.a;

}

ENDCG

} 

FallBack "Diffuse"

}

 

 

code end -----------------------------------------------------------------------

通过对比变量,我们只是把之前的遮罩贴图换为了法线贴图。但是我们就是想要逐像素的法线贴图来修改我们的反射立方体图效果,

为了实现这一步,必须在法线贴图应用到着色器之后得到物体表面的法线信息,所以我们通过UnpackNormal方法获得法线的rgb信息。

然后再传递给ouput输出结构体的Normal属性。这时候着色器表面的法线就会被修改。因此,我们需要借助它来对我们的反射进行修改,

借助Input结构体进行传递,于是我们用到了内置的INTERNAL_DATA变量来访问修改后的法线。然后再通过WorldReflectionVector(IN,o.Normal)函数来计算游戏场景世界的反射向量,

(WorldReflectionVector)函数中计算每个像素(per-pixel)反射向量(reflection vector)

这是Unity给我们提供的一种内置函数,方便我们完成功能。最后,我们的效果如下:

左侧是我们刚刚完成的发现贴图效果,中间是上一篇带遮罩的效果。