Cg Programming/Unity/Lighting Textured Surfaces光照纹理表面

这里写图片描述
本教程涵盖了纹理表面的逐顶点光照。
它结合了章节“纹理球体”和章节“镜面高光”的着色器代码,使用由一张贴图决定的漫反射材质颜色来计算光照。如果你没有读过那些章节,这会是一个非常棒的机会来阅读它们。

纹理及漫反射逐顶点光照

在章节“纹理球体”中,纹理颜色被用作片元着色器的输出。但是,也有可能使用纹理颜色作为光照计算中的任意参数,特别是对于漫反射中的材质常量这里写图片描述,它在章节“漫反射”中有过介绍。它出现在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.
恭喜,你学完了本章。我们知道了:

  • 纹理和逐顶点光照通常是如何结合的。
  • “独立镜面颜色”是什么。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
水资源是人类社会的宝贵财富,在生活、工农业生产中是不可缺少的。随着世界人口的增长及工农业生产的发展,需水量也在日益增长,水已经变得比以往任何时候都要珍贵。但是,由于人类的生产和生活,导致水体的污染,水质恶化,使有限的水资源更加紧张。长期以来,油类物质(石油类物质和动植物油)一直是水和土壤中的重要污染源。它不仅对人的身体健康带来极大危害,而且使水质恶化,严重破坏水体生态平衡。因此各国都加强了油类物质对水体和土壤的污染的治理。对于水中油含量的检测,我国处于落后阶段,与国际先进水平存在差距,所以难以满足当今技术水平的要求。为了取得具有代表性的正确数据,使分析数据具有与现代测试技术水平相应的准确性和先进性,不断提高分析成果的可比性和应用效果,检测的方法和仪器是非常重要的。只有保证了这两方面才能保证快速和准确地测量出水中油类污染物含量,以达到保护和治理水污染的目的。开展水中油污染检测方法、技术和检测设备的研究,是提高水污染检测的一条重要措施。通过本课题的研究,探索出一套适合我国国情的水质污染现场检测技术和检测设备,具有广泛的应用前景和科学研究价值。 本课题针对我国水体的油污染,探索一套检测油污染的可行方案和方法,利用非分散红外光度法技术,开发研制具有自主知识产权的适合国情的适于野外便携式的测油仪。利用此仪器,可以检测出被测水样中亚甲基、甲基物质和动植物油脂的污染物含量,为我国众多的环境检测站点监测水体的油污染状况提供依据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值