Unity3D之高级渲染 Shader Forge
Shader Forge 是一款极为实用的组件,尤其对于那些对 Shader 编程理解不深的开发者而言,它能帮助开发者快速搭建出一个 Shader。这一点与虚幻的 UE4 引擎编辑器颇为相似,在次世代游戏开发中表现出色。下面将为大家展示 Shader Forge 的强大功能。
效果展示
Shader Forge 搭建效果
上图展示的效果是使用 Shader Forge 搭建出来的,其中运用了 Diffuse(漫反射)、Normal(法线)、Gloss(光泽度)、Emisson(自发光)等效果。
Unity3D 引擎自带 Shader 效果
这是在相同环境下,使用 Unity3D 引擎自带的 standardShader 的效果,其设置界面如下:
通过对比可以发现,Unity3D 引擎自带的 Shader 难以满足我们的需求,此时就可以借助 Shader Forge 来解决问题。
Shader Forge 编辑器
Shader Forge 提供了一个编辑器,上篇博客中已经介绍过关于材质之间的操作,Shader Forge 编辑器也是基于此原理进行操作的,其效果如下:
在 Unity3D 编辑器中的表现如下:
参数可以根据实际效果进行随意调整,使用这个模型可以实现高光、法线以及自发光等效果。
Shader 代码实现
通过 Shader Forge 生成的 Shader 代码采用了顶点着色器和片段着色器。将上述效果转化成 Shader 后,核心代码如下:
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.uv0 = v.texcoord0;
o.normalDir = UnityObjectToWorldNormal(v.normal);
o.tangentDir = normalize( mul( unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 ) ).xyz );
o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w);
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
float3 lightColor = _LightColor0.rgb;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
UNITY_TRANSFER_FOG(o,o.pos);
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
float4 frag(VertexOutput i) : COLOR {
i.normalDir = normalize(i.normalDir);
float3x3 tangentTransform = float3x3( i.tangentDir, i.bitangentDir, i.normalDir);
float3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
float3 _normal_var = UnpackNormal(tex2D(_normal,TRANSFORM_TEX(i.uv0, _normal)));
float3 normalLocal = _normal_var.rgb;
float3 normalDirection = normalize(mul( normalLocal, tangentTransform )); // Perturbed normals
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
float3 lightColor = _LightColor0.rgb;
float3 halfDirection = normalize(viewDirection+lightDirection);
////// Lighting:
float attenuation = LIGHT_ATTENUATION(i);
float3 attenColor = attenuation * _LightColor0.xyz;
///////// Gloss:
float4 _gloss_diffuse_var = tex2D(_gloss_diffuse,TRANSFORM_TEX(i.uv0, _gloss_diffuse));
float gloss = (_gloss_diffuse_var.r*_gloss);
float specPow = exp2( gloss * 10.0+1.0);
////// Specular:
float NdotL = max(0, dot( normalDirection, lightDirection ));
float4 _light_var = tex2D(_light,TRANSFORM_TEX(i.uv0, _light));
float3 specularColor = (_light_var.rgb*_light_slider);
float3 directSpecular = (floor(attenuation) * _LightColor0.xyz) * pow(max(0,dot(halfDirection,normalDirection)),specPow)*specularColor;
float3 specular = directSpecular;
/////// Diffuse:
NdotL = max(0.0,dot( normalDirection, lightDirection ));
float3 directDiffuse = max( 0.0, NdotL) * attenColor;
float3 indirectDiffuse = float3(0,0,0);
indirectDiffuse += UNITY_LIGHTMODEL_AMBIENT.rgb; // Ambient Light
float4 _df_var = tex2D(_df,TRANSFORM_TEX(i.uv0, _df));
float3 diffuseColor = (_df_var.rgb*_df_Color.rgb);
float3 diffuse = (directDiffuse + indirectDiffuse) * diffuseColor;
////// Emissive:
float4 _Emission_color_var = tex2D(_Emission_color,TRANSFORM_TEX(i.uv0, _Emission_color));
float3 emissive = (_Emission_color_var.rgb*_Emission_slider);
/// Final Color:
float3 finalColor = diffuse + specular + emissive;
fixed4 finalRGBA = fixed4(finalColor,1);
UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
return finalRGBA;
}
性能表现
通过上述代码,我们实现了次世代效果渲染,是不是非常酷炫?很多人会担心其性能问题,实际上在 IOS 端,其帧率表现尚可。在满帧 30 的情况下,能达到 25 帧左右。