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

纹理及漫反射逐顶点光照

在章节“纹理球体”中,纹理颜色被用作片元着色器的输出。但是,也有可能使用纹理颜色作为光照计算中的任意参数,特别是对于漫反射中的材质常量,它在章节“漫反射”中有过介绍。它出现在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 propertiesuniform 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 attenuationlightDirection = 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 sourcesBlend 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 propertiesuniform 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 attenuationlightDirection = 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 ambientoutput.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/Lighting Textured Surfaces光照纹理表面相关推荐

  1. Cg Programming/Unity/Reflecting Surfaces反射表面

    本教程介绍了反射贴图(以及实现它的立方体贴图). 这是Unity中使用立方体贴图的环境映射的一系列小教程中的第一篇.本章基于章节"平滑镜面高光"中介绍的逐像素光照以及章节" ...

  2. Cg Programming/Unity/Brushed Metal拉丝金属

    本教程涵盖了各向异性镜面高光. 这是几个关于光照教程中的其中一个教程,这个光照超出了Phone反射模型的范围.但是,它是基于章节"镜面高光"(逐顶点光照)以及章节"光滑镜 ...

  3. Unity Lighting -- 室内场景光照和发光材质

    室内场景光照需要考虑的重点问题 在为室内场景做光照设计的时候,间接光照非常重要.大部分室内场景的光线会经过多次反射后才进入到了我们的眼睛(或者说是Unity的摄像机).环境光和反射光在室内场景中为场景 ...

  4. Unity Lighting -- 室内场景光照杂项

    游戏物体所有面都计算阴影 在游戏物体的Inspector中,展开Lighting选项卡,在Cast Shadows中选择 Two Sided. 选择Two Sided后,游戏物体在计算阴影的时候会对M ...

  5. Cg Programming/Unity/Specular Highlights镜面高光

    本教程涵盖了使用Phone反射模型的逐顶点光照(也叫做高洛德着色).它在章节"漫反射"中通过两个额外的术语扩展了着色器代码:环境光和镜面反射.这三个术语一起构成了Phone反射模型 ...

  6. Unity Lighting(一)光照练习

    Unity 2018.1.2f1 原文链接:https://www.youtube.com/watch?v=VnG2gOKV9dw Unity Lighting练习最终效果 眼睛.光源与物体 光学基础 ...

  7. unity入门精要之第6 章 Unity 中的基础光照--环境光和自发光

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 一.Unity 中的环境光和自发光 二.在Unity Shader 中实现漫反射光照模型 参考 前言 但这种模型有很多局限性.首先,有很 ...

  8. unity入门精要之第6 章 Unity 中的基础光照---实现高光反射光照模型

    Unity系列文章目录 文章目录 Unity系列文章目录 前言 参考 前言 在6.2.4 节中,我们给出了基本光照模型中高光反射部分的计算公式: 从公式可以看出,要计算高光反射需要知道4 个参数:入射 ...

  9. 【无标Unity基于ShaderLab实现光照系统(着色器代码实现小结)

    文章来源: 学习通http://www.bdgxy.com/ 普学网http://www.boxinghulanban.cn/ 智学网http://www.jaxp.net/ 表格制作excel教程h ...

最新文章

  1. corosync+pacemaker+crmsh的高可用web集群的实现
  2. Linux Rootkit 系列五:感染系统关键内核模块实现持久化
  3. 做到这23条,你就成熟了!
  4. 6 有序集合ZSet(Sorted Set)
  5. JS魔法堂:doctype我们应该了解的基础知识
  6. 玛氏携手阿里 天猫网罗全球快消三巨头
  7. Yii 2 的安装 之 踩坑历程
  8. 基于java百货中心供应链管理系统(含源文件)
  9. atitit. web 在线文件管理器最佳实践(1)--- elFinder 的使用流程解决之道 。打开浏览服务器文件夹java .net php
  10. 发动机压缩比怎么计算公式_加几号油它说的算 解析发动机压缩比奥秘
  11. P5_扩展卡尔曼滤波器_udacity无人驾驶
  12. Hibernate检索策略
  13. 你未来的职业规划是什么?
  14. Linux操作系统学习笔记【入门必备】
  15. 怎么将几个QQ对话窗口合并和分离
  16. [530]Win10怎么打开注册表编辑器
  17. 激光三角测距原理概述
  18. 计算机计划300字作文,计划作文300字七篇
  19. bert源码之中_run_strip_accents(text)函数解读
  20. 远程在线办公效率与业绩提升秘笈

热门文章

  1. ZOJ:3716 Ribbon Gymnastics
  2. Eclipse平台技术概述
  3. 小米手机升级MIUI11后,要记得关闭这4个按钮,不然电池就会不耐用
  4. 以蜜代糖促进心脑血管健康
  5. K8S实战基础篇:一文带你深入了解K8S实战部署SpringBoot项目
  6. 搭建网站,和把大象装冰箱一样简单?
  7. python网络爬虫学习资料
  8. 影响计算机安全的诸多因素中,影响计算机设备安全的诸多因素中,影响较大的是()。...
  9. 关于前后端分离的概念,作用,优缺点
  10. 【集成学习(上)】My_Task03掌握偏差与方差理论 笔记