解读Unity中的CG编写Shader系列十 (光滑的镜面反射(冯氏着色))
前文完成了最基本的镜面反射着色器,单平行光源下的逐顶点着色(per-vertex lighting),又称为古罗着色(Gouraud shading)。这篇文章作为后续讨论更光滑的镜面反射方式,逐像素着色(per-pixcel lighting),又称为冯氏着色(Phong shading)
逐像素着色Per-Pixel Lighting (冯氏着色Phong Shading)
将前文的古罗着色改为冯氏着色
//定义顶点着色的输出结构体/片段着色的输入结构体
//去掉颜色 添加顶点的世界坐标以及法向量,这里的语义使用了TEXCOORD的两个集合,这里的TEXCOORD是我们自己使用的,与顶点着色器输入时使用该语义 已经有区别了 struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
};
Shader "Custom/PhoneShadingSpecular" {
Properties {
_Color ("Diffuse Material Color", 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
//获取property中定义的材料颜色
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
// 光源的位置或者方向
//uniform float4 _WorldSpaceLightPos0;
// 光源的颜色 (from "Lighting.cginc")
uniform float4 _LightColor0;
//定义顶点着色器的输入参数结构体
//我们只需要每个顶点的位置与对应的法向量
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;
//对象坐标系到世界坐标系的变换矩阵
//_Object2World与_World2Object均为unity提供的内置uniform参数
float4x4 modelMatrix = _Object2World;
//世界坐标系到对象坐标系的变换矩阵
float4x4 modelMatrixInverse = _World2Object;
//法向量N变化至对象坐标系
output.normalDir = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse)));
//将顶点坐标向世界坐标系变换
output.posWorld=mul(modelMatrix,input.vertex);
//国际惯例,顶点变化三步曲
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
//片段着色器,老规矩,把顶点着色器的输出参数作为片段着色器的输入参数
float4 frag(vertexOutput input): COLOR
{
//接受顶点着色器传递的法向量与顶点世界坐标
//这里必须将法向量再normalize一次
//尽管在顶点着色器中已经normalize了一次
float3 normalDirection=normalize(input.normalDir);
float3 worldPosition=input.posWorld;
//观察向量V由摄像机坐标与顶点坐标矢量相减
//这里改顶点坐标为上面获取到的世界坐标
float3 viewDirection = normalize(float3(float4(_WorldSpaceCameraPos, 1.0)
- worldPosition));
/*下面的部分直接招搬就好了*/
//平行光源的入射向量L直接由uniform_WorldSpaceLightPos0给出
float3 lightDirection =normalize(float3(_WorldSpaceLightPos0));
//镜面反射光的计算
float3 specularReflection=float3(_LightColor0)*float3(_SpecColor)*pow(max(0.0,dot(reflect(-lightDirection, normalDirection),viewDirection)),_Shininess);
//前文计算好的漫反射光
float3 diffuseReflection=float3(_LightColor0) * float3(_Color)* max(0.0, dot(normalDirection, lightDirection));
//环境光直接获取
float3 ambientLighting = float3(UNITY_LIGHTMODEL_AMBIENT) * float3(_Color);
//根据冯氏反射模型将上述3个RGB颜色向量相加,然后补充A:
return float4(ambientLighting + diffuseReflection+ specularReflection, 1.0);;
}
ENDCG
}
}
FallBack "Diffuse"
}
最后的效果图,我们与上一个例子中的球体进行对比:
解读Unity中的CG编写Shader系列十 (光滑的镜面反射(冯氏着色))的更多相关文章
- 解读Unity中的CG编写Shader系列八(镜面反射)
转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...
- [转]解读Unity中的CG编写Shader系列9——镜面反射
讨论完漫反射之后,接下来肯定就是镜面反射了在开始镜面反射shader的coding之前,要扩充一下前面提到的知识,加深理解镜面反射与漫反射的区别.注:这篇文章实现的镜面反射是逐顶点着色(per-ver ...
- [转]解读Unity中的CG编写Shader系列7——漫反射
如果前面几个系列文章的内容过于冗长缺乏趣味着实见谅,由于时间原因前面的混合部分还没有写完,等以后再补充,现在开始关于反射的内容了.折射与反射在物理世界中,光的反射与折射往往是同时存在的,光源由真空或者 ...
- 解读Unity中的CG编写Shader系列七(不透明度与混合)
转自http://www.itnose.net/detail/6098539.html 1.不透明度 当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段 ...
- 解读Unity中的CG编写Shader系列三
转自http://www.itnose.net/detail/6096068.html 在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章 ...
- [转]解读Unity中的CG编写Shader系列6——不透明度与混合
1.不透明度当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段着色器以及后面的环节的主要工作是输出颜色与深度到帧缓存中,所以两个纹理在每个像素上的颜色到 ...
- [转]解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
在上一个例子中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上.这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁.后面 ...
- 解读Unity中的CG编写Shader系列3——表面剔除与剪裁模式
在上一个样例中,我们得到了由mesh组件传递的信息经过数学转换至合适的颜色区间以颜色的形式着色到物体上. 这篇文章将要在此基础上研究片段的擦除(discarding fragments)和前面剪裁.后 ...
- 解读Unity中的CG编写Shader系列四(unity中的圆角矩形shader)
转自 http://www.itnose.net/detail/6097625.html 上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做 ...
随机推荐
- NSUserDefaults standardUserDefaults的使用
本地存储数据简单的说有三种方式:数据库.NSUserDefaults和文件. NSUserDefaults用于存储数据量小的数据,例如用户配置.并不是所有的东西都能往里放的,只支持:NSString, ...
- 给各位聚聚和大大介绍一个开源项目 Expression2Sql(转)
阅读目录 一.Expression2Sql介绍 二.单表简单查询 三.Where条件 四.多表关联查询 五.group by 六.order by 七.函数 八.delete 删除 九.update ...
- the usage of linux command "expect"
#! /usr/bin/expect -f# this script is used to practise the command "expect" #when "li ...
- C#集合u
List<T> 列表(动态数组),相当于C++的 vector Queue<T> 队列,先进先出 Stack<T> 栈,先进后出 LinkedList<T&g ...
- Nginx如何隐藏index.html
我要隐藏目录下的index.html,修改Nginux配置如下: 1.修改文档顺序 index index.html index.php 2.开启目录流量 在server或location 段里添加 ...
- Hadoop Fsimage 和 editlog
在<Hadoop NameNode元数据相关文件目录解析>文章中提到NameNode的$dfs.namenode.name.dir/current/文件夹的几个文件: 1 current/ ...
- POJ 2155 Matrix
二维树状数组.... Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissio ...
- protect和private 的区别
protect和private 的区别 public 表示全局,类内部外部子类都可以访问: private表示私有的,只有本类内部可以使用: protected表示受保护的,只有本类或子类或父类中可以 ...
- eclipse安装spring插件
1.打开eclipse点击help,点击about eclipse 2.点击最左侧图票查看eclipse版本 3.查看版本 4.进入http://spring.io/tools/sts/all,选择适 ...
- C# 读写App.config
Jul142013 [C#] 读写App.config配置文件的方法 作者:xieyc 发布:2013-07-14 17:29 字符数:3433 分类:编程 阅读: 39,139 次 ...