Cg Programming/Unity/Two-Sided Smooth Surfaces双面平滑曲面

来源:互联网 发布:便宜域名注册 编辑:程序博客网 时间:2024/04/29 11:31

这里写图片描述
本教程涵盖了双面逐像素光照(也就是双面Phong着色)。
在这里我们会把章节“平滑镜面高光”中讨论的逐像素光照跟章节“双面曲面”中讨论的双面光照结合起来。

着色器代码

章节“平滑镜面高光”中的代码所需的更改如下:背面材质的新属性,复制一份有前面剔除的通道,再复制一份有背面剔除的通道,以及为背面的渲染准备负向表面法向量。实际上非常简单,代码如下:

Shader "Cg two-sided per-pixel lighting" {   Properties {      _Color ("Diffuse Material Color", Color) = (1,1,1,1)       _SpecColor ("Specular Material Color", Color) = (1,1,1,1)       _Shininess ("Shininess", Float) = 10      _BackColor ("Back Material Diffuse Color", Color) = (1,1,1,1)       _BackSpecColor ("Back Material Specular Color", Color)          = (1,1,1,1)       _BackShininess ("Back Material Shininess", Float) = 10   }   SubShader {      Pass {             Tags { "LightMode" = "ForwardBase" }             // pass for ambient light and first light source         Cull Back // render only front faces         CGPROGRAM         #pragma vertex vert           #pragma fragment frag          #include "UnityCG.cginc"         uniform float4 _LightColor0;             // color of light source (from "Lighting.cginc")         // User-specified properties         uniform float4 _Color;          uniform float4 _SpecColor;          uniform float _Shininess;         uniform float4 _BackColor;          uniform float4 _BackSpecColor;          uniform float _BackShininess;         struct vertexInput {            float4 vertex : POSITION;            float3 normal : NORMAL;         };         struct vertexOutput {            float4 pos : SV_POSITION;            float4 posWorld : TEXCOORD0;            float3 normalDir : TEXCOORD1;         };         vertexOutput vert(vertexInput input)          {            vertexOutput output;            float4x4 modelMatrix = _Object2World;            float4x4 modelMatrixInverse = _World2Object;             output.posWorld = mul(modelMatrix, input.vertex);            output.normalDir = normalize(               mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);            return output;         }         float4 frag(vertexOutput input) : COLOR         {            float3 normalDirection = normalize(input.normalDir);            float3 viewDirection = normalize(               _WorldSpaceCameraPos - input.posWorld.xyz);            float3 lightDirection;            float attenuation;            if (0.0 == _WorldSpaceLightPos0.w) // directional light?            {               attenuation = 1.0; // no attenuation               lightDirection = normalize(_WorldSpaceLightPos0.xyz);            }             else // point or spot light            {               float3 vertexToLightSource =                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;               float distance = length(vertexToLightSource);               attenuation = 1.0 / distance; // linear attenuation                lightDirection = normalize(vertexToLightSource);            }            float3 ambientLighting =                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;            float3 diffuseReflection =                attenuation * _LightColor0.rgb * _Color.rgb               * max(0.0, dot(normalDirection, lightDirection));            float3 specularReflection;            if (dot(normalDirection, lightDirection) < 0.0)                // light source on the wrong side?            {               specularReflection = float3(0.0, 0.0, 0.0);                   // no specular reflection            }            else // light source on the right side            {               specularReflection = attenuation * _LightColor0.rgb                   * _SpecColor.rgb * pow(max(0.0, dot(                  reflect(-lightDirection, normalDirection),                   viewDirection)), _Shininess);            }            return float4(ambientLighting + diffuseReflection                + specularReflection, 1.0);         }         ENDCG      }      Pass {             Tags { "LightMode" = "ForwardAdd" }             // pass for additional light sources         Blend One One // additive blending          Cull Back // render only front faces         CGPROGRAM         #pragma vertex vert           #pragma fragment frag          #include "UnityCG.cginc"         uniform float4 _LightColor0;             // color of light source (from "Lighting.cginc")         // User-specified properties         uniform float4 _Color;          uniform float4 _SpecColor;          uniform float _Shininess;         uniform float4 _BackColor;          uniform float4 _BackSpecColor;          uniform float _BackShininess;         struct vertexInput {            float4 vertex : POSITION;            float3 normal : NORMAL;         };         struct vertexOutput {            float4 pos : SV_POSITION;            float4 posWorld : TEXCOORD0;            float3 normalDir : TEXCOORD1;         };         vertexOutput vert(vertexInput input)          {            vertexOutput output;            float4x4 modelMatrix = _Object2World;            float4x4 modelMatrixInverse = _World2Object;             output.posWorld = mul(modelMatrix, input.vertex);            output.normalDir = normalize(               mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);            return output;         }         float4 frag(vertexOutput input) : COLOR         {            float3 normalDirection = normalize(input.normalDir);            float3 viewDirection = normalize(               _WorldSpaceCameraPos - input.posWorld.xyz);            float3 lightDirection;            float attenuation;            if (0.0 == _WorldSpaceLightPos0.w) // directional light?            {               attenuation = 1.0; // no attenuation               lightDirection = normalize(_WorldSpaceLightPos0.xyz);            }             else // point or spot light            {               float3 vertexToLightSource =                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;               float distance = length(vertexToLightSource);               attenuation = 1.0 / distance; // linear attenuation                lightDirection = normalize(vertexToLightSource);            }            float3 diffuseReflection =                attenuation * _LightColor0.rgb * _Color.rgb               * max(0.0, dot(normalDirection, lightDirection));            float3 specularReflection;            if (dot(normalDirection, lightDirection) < 0.0)                // light source on the wrong side?            {               specularReflection = float3(0.0, 0.0, 0.0);                   // no specular reflection            }            else // light source on the right side            {               specularReflection = attenuation * _LightColor0.rgb                   * _SpecColor.rgb * pow(max(0.0, dot(                  reflect(-lightDirection, normalDirection),                   viewDirection)), _Shininess);            }            return float4(diffuseReflection                + specularReflection, 1.0);               // no ambient lighting in this pass         }         ENDCG      }      Pass {             Tags { "LightMode" = "ForwardBase" }             // pass for ambient light and first light source         Cull Front // render only back faces         CGPROGRAM         #pragma vertex vert           #pragma fragment frag          #include "UnityCG.cginc"         uniform float4 _LightColor0;             // color of light source (from "Lighting.cginc")         // User-specified properties         uniform float4 _Color;          uniform float4 _SpecColor;          uniform float _Shininess;         uniform float4 _BackColor;          uniform float4 _BackSpecColor;          uniform float _BackShininess;         struct vertexInput {            float4 vertex : POSITION;            float3 normal : NORMAL;         };         struct vertexOutput {            float4 pos : SV_POSITION;            float4 posWorld : TEXCOORD0;            float3 normalDir : TEXCOORD1;         };         vertexOutput vert(vertexInput input)          {            vertexOutput output;            float4x4 modelMatrix = _Object2World;            float4x4 modelMatrixInverse = _World2Object;             output.posWorld = mul(modelMatrix, input.vertex);            output.normalDir = normalize(               mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);            return output;         }         float4 frag(vertexOutput input) : COLOR         {            float3 normalDirection = normalize(input.normalDir);            float3 viewDirection = normalize(               _WorldSpaceCameraPos - input.posWorld.xyz);            float3 lightDirection;            float attenuation;            if (0.0 == _WorldSpaceLightPos0.w) // directional light?            {               attenuation = 1.0; // no attenuation               lightDirection = normalize(_WorldSpaceLightPos0.xyz);            }             else // point or spot light            {               float3 vertexToLightSource =                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;               float distance = length(vertexToLightSource);               attenuation = 1.0 / distance; // linear attenuation                lightDirection = normalize(vertexToLightSource);            }            float3 ambientLighting =                UNITY_LIGHTMODEL_AMBIENT.rgb * _BackColor.rgb;            float3 diffuseReflection =                attenuation * _LightColor0.rgb * _BackColor.rgb               * max(0.0, dot(normalDirection, lightDirection));            float3 specularReflection;            if (dot(normalDirection, lightDirection) < 0.0)                // light source on the wrong side?            {               specularReflection = float3(0.0, 0.0, 0.0);                   // no specular reflection            }            else // light source on the right side            {               specularReflection = attenuation * _LightColor0.rgb                   * _BackSpecColor.rgb * pow(max(0.0, dot(                  reflect(-lightDirection, normalDirection),                   viewDirection)), _BackShininess);            }            return float4(ambientLighting + diffuseReflection                + specularReflection, 1.0);         }         ENDCG      }      Pass {             Tags { "LightMode" = "ForwardAdd" }             // pass for additional light sources         Blend One One // additive blending          Cull Front // render only back faces         CGPROGRAM         #pragma vertex vert           #pragma fragment frag          #include "UnityCG.cginc"         uniform float4 _LightColor0;             // color of light source (from "Lighting.cginc")         // User-specified properties         uniform float4 _Color;          uniform float4 _SpecColor;          uniform float _Shininess;         uniform float4 _BackColor;          uniform float4 _BackSpecColor;          uniform float _BackShininess;         struct vertexInput {            float4 vertex : POSITION;            float3 normal : NORMAL;         };         struct vertexOutput {            float4 pos : SV_POSITION;            float4 posWorld : TEXCOORD0;            float3 normalDir : TEXCOORD1;         };         vertexOutput vert(vertexInput input)          {            vertexOutput output;            float4x4 modelMatrix = _Object2World;            float4x4 modelMatrixInverse = _World2Object;             output.posWorld = mul(modelMatrix, input.vertex);            output.normalDir = normalize(               mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);            return output;         }         float4 frag(vertexOutput input) : COLOR         {            float3 normalDirection = normalize(input.normalDir);            float3 viewDirection = normalize(               _WorldSpaceCameraPos - input.posWorld.xyz);            float3 lightDirection;            float attenuation;            if (0.0 == _WorldSpaceLightPos0.w) // directional light?            {               attenuation = 1.0; // no attenuation               lightDirection = normalize(_WorldSpaceLightPos0.xyz);            }             else // point or spot light            {               float3 vertexToLightSource =                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;               float distance = length(vertexToLightSource);               attenuation = 1.0 / distance; // linear attenuation                lightDirection = normalize(vertexToLightSource);            }            float3 diffuseReflection =                attenuation * _LightColor0.rgb * _BackColor.rgb               * max(0.0, dot(normalDirection, lightDirection));            float3 specularReflection;            if (dot(normalDirection, lightDirection) < 0.0)                // light source on the wrong side?            {               specularReflection = float3(0.0, 0.0, 0.0);                   // no specular reflection            }            else // light source on the right side            {               specularReflection = attenuation * _LightColor0.rgb                   * _BackSpecColor.rgb * pow(max(0.0, dot(                  reflect(-lightDirection, normalDirection),                   viewDirection)), _BackShininess);            }            return float4(diffuseReflection                + specularReflection, 1.0);               // no ambient lighting in this pass         }         ENDCG      }   }   Fallback "Specular"}

总结

恭喜你完成了本教程。我们学习了:

  • 双曲面表面如何用逐像素光照绘制。

深入阅读

如果你想了解地更多:

  • 关于单面逐像素光照的着色器版本,你应该阅读章节“平滑镜面高光”。
  • 关于双面逐像素光照的着色器版本,你应该阅读章节“双面曲面”。
阅读全文
0 0
原创粉丝点击