Cg Programming/Unity/Lighting Textured Surfaces光照纹理表面
2017-11-01 19:36
495 查看
本教程涵盖了纹理表面的逐顶点光照。
它结合了章节“纹理球体”和章节“镜面高光”的着色器代码,使用由一张贴图决定的漫反射材质颜色来计算光照。如果你没有读过那些章节,这会是一个非常棒的机会来阅读它们。
纹理及漫反射逐顶点光照
在章节“纹理球体”中,纹理颜色被用作片元着色器的输出。但是,也有可能使用纹理颜色作为光照计算中的任意参数,特别是对于漫反射中的材质常量,它在章节“漫反射”中有过介绍。它出现在Phong反射模型中的漫射部分:
这个方程中对于三个颜色分量红、绿和蓝使用了不同的材质常量。通过使用一张贴图来决定这些材质常量,它们可以在表面上变化。
着色器代码
跟章节“镜面高光”中的逐顶点光照相比,这里的顶点着色器计算了额外的输出颜色:漫射颜色和镜面颜色,它们使用语义TEXCOORD1和TEXCOORD2。在片元着色器中,参数diffuseColor跟贴图颜色相乘,并且specularColor就是镜面反射项,它不应该乘以纹理颜色。这是完全有道理的,但出于历史原因(也就是老的图形硬件不支持),它有时也被称作“单独的镜面颜色”;实际上,Unity的ShaderLab有一个选项“SeparateSpecular” 会激活或者禁用它。
注意属性_Color会被包含,它会乘以漫射颜色的所有部分(分量);因此,它作为一个有用的颜色过滤器来着色或者阴影纹理颜色。
此外,有这个名字的属性必须使得备用着色器生效(也可以查看章节“漫反射”中关于备用着色器的讨论)。
Shader "Cg per-vertex lighting with texture" { Properties { _MainTex ("Texture For Diffuse Material Color", 2D) = "white" {} _Color ("Overall Diffuse Color Filter", Color) = (1,1,1,1) _SpecColor ("Specular Material Color", Color) = (1,1,1,1) _Shininess ("Shininess", Float) = 10 } SubShader { Pass { Tags { "LightMode" = "ForwardBase" } // 环境光和第一个光源的通道 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source (from "Lighting.cginc") // User-specified properties uniform sampler2D _MainTex; uniform float4 _Color; uniform float4 _SpecColor; uniform float _Shininess; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float3 diffuseColor : TEXCOORD1; float3 specularColor : TEXCOORD2; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = _Object2World; float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize( mul(float4(input.normal, 0.0), modelMatrixInverse).xyz); float3 viewDirection = normalize(_WorldSpaceCameraPos - mul(modelMatrix, input.vertex).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 - mul(modelMatrix, input.vertex).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); } output.diffuseColor = ambientLighting + diffuseReflection; output.specularColor = specularReflection; output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { return float4(input.specularColor + input.diffuseColor * tex2D(_MainTex, input.tex.xy), 1.0); } ENDCG } Pass { Tags { "LightMode" = "ForwardAdd" } // pass for additional light sources Blend One One // additive blending CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source (from "Lighting.cginc") // User-specified properties uniform sampler2D _MainTex; uniform float4 _Color; uniform float4 _SpecColor; uniform float _Shininess; struct vertexInput { float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord : TEXCOORD0; }; struct vertexOutput { float4 pos : SV_POSITION; float4 tex : TEXCOORD0; float3 diffuseColor : TEXCOORD1; float3 specularColor : TEXCOORD2; }; vertexOutput vert(vertexInput input) { vertexOutput output; float4x4 modelMatrix = _Object2World; float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize( mul(float4(input.normal, 0.0), modelMatrixInverse).xyz); float3 viewDirection = normalize(_WorldSpaceCameraPos - mul(modelMatrix, input.vertex).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 - mul(modelMatrix, input.vertex).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); } output.diffuseColor = diffuseReflection; // no ambient output.specularColor = specularReflection; output.tex = input.texcoord; output.pos = mul(UNITY_MATRIX_MVP, input.vertex); return output; } float4 frag(vertexOutput input) : COLOR { return float4(input.specularColor + input.diffuseColor * tex2D(_MainTex, input.tex.xy), 1.0); } ENDCG } } Fallback "Specular" }
In order to assign a texture image to this shader, you should follow the steps discussed in Section “Textured Spheres”.
为了把纹理贴图指定到这个着色器,你应该遵循“纹理球体”中讨论的步骤。
总结
Congratulations, you have reached the end. We have looked at:How texturing and per-vertex lighting are usually combined.
What a “separate specular color” is.
恭喜,你学完了本章。我们知道了:
纹理和逐顶点光照通常是如何结合的。
“独立镜面颜色”是什么。
相关文章推荐
- Cg Programming/Unity/Reflecting Surfaces反射表面
- Cg Programming/Unity/Layers of Textures纹理的层级
- Cg Programming/Unity/Transparent Textures透明纹理
- Cg Programming/Unity/Glossy Textures光泽纹理
- Cg Programming/Unity/Two-Sided Surfaces双面表面
- Cg Programming/Unity/Cookies
- 《CG Programming in Unity》笔记1-基础知识
- 解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
- Unity旧延迟光照渲染路径( Legacy Deferred Lighting Rendering Path)
- 3ds Max光照纹理导入Unity的教程.
- 3ds Max光照纹理导入Unity的教程.
- Unity - 基础 - Unity 5 光照与渲染(Lighting and Rendering)
- Cg Programming/Unity/Cutaways
- Cg Programming/Unity/Transparency
- wiki/Cg Programming/Unity_shder/RGB Cube
- Cg Programming/Unity
- Cg Programming/Unity/Smooth Specular Highlights平滑镜面高光
- 解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
- Cg Programming/Unity 目录
- Cg Programming/Unity/Soft Shadows of Spheres球体的软阴影