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
- Cg Programming/Unity/Two-Sided Smooth Surfaces双面平滑曲面
- Cg Programming/Unity/Two-Sided Surfaces双面表面
- Cg Programming/Unity/Lighting of Bumpy Surfaces凹凸曲面光照
- Cg Programming/Unity/Smooth Specular Highlights平滑镜面高光
- Cg Programming/Unity/Reflecting Surfaces反射表面
- Cg Programming/Unity/Translucent Surfaces半透明表面
- Cg Programming/Unity/Curved Glass曲面玻璃
- GLSL-双面渲染技术(Two-sided rendering)
- Cg Programming/Unity/Lighting Textured Surfaces光照纹理表面
- Cg two-sided per-vertex lighting
- Cg two-sided per-pixel lighting
- 【OpenGL】GLSL-双面渲染技术(Two-sided rendering)
- Cg Programming/Unity 目录
- Cg Programming/Unity/Transparency
- Cg Programming/Unity
- Cg Programming/Unity/Cutaways
- Cg Programming/Unity/Cookies
- wiki/Cg Programming/Unity/Cutaways
- 3011: [Usaco2012 Dec]Running Away From the Barn
- 将二叉树拆成链表-LintCode
- Periodic Strings UVA
- 信息学奥赛一本通(C++版) 第一部分 C++语言 第一章 C++语言入门
- java面试题之集合框架
- Cg Programming/Unity/Two-Sided Smooth Surfaces双面平滑曲面
- [CQOI2007]涂色paint dp(区间)
- bnu 10790 Periodic Table of Elements(模拟)
- socket中的read返回0
- 纪念一次搭建git服务器所踩的坑,最详细全部过程 | ssh | git | centos
- 《Machine Learning》第三讲 逻辑回归(LR)
- maven版本对应jdk版本要求
- Android 之路1---安装配置环境Mac版
- 代码:小波包分解与重构、小波包能量特征提取