解读Unity中的CG编写Shader系列八(多光源漫反射)
转自http://www.itnose.net/detail/6117338.html
前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下我们的物体表面的漫反射强度如何叠加在一起呢?前文打的tag "LightMode"="ForwardBase"又是什么意思呢?
Unity内置的DiffuseShader,也就是我们创建一个Material出来时默认的Shader也是多光源的,所以这篇文章完成的shader与默认的diffuse shader基本效果一致。
首先引入几个概念
渲染路径 Rendering Path
像素光 Pixel Light
关于像素光的叠加原理
Blend One One
Shader "Custom/Multi-Light Diffuse" {
Properties {
//材料颜色默认为黑色,可在inspector中调节
_Color ("Material Color", Color) = (1,1,1,1)
}
SubShader {
Pass{
//第一个像素光所在的反射通道标记为ForwardBase
Tags {"LightMode" = "ForwardBase"}
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
//#pragma exclude_renderers gles
//定义顶点着色器与片段着色器入口
#pragma vertex vert
#pragma fragment frag
//获取property中定义的材料颜色
uniform float4 _Color;
// 光源的位置或者方向
//uniform float4 _WorldSpaceLightPos0;
// 光源的颜色 (from "Lighting.cginc")
uniform float4 _LightColor0;
//定义顶点着色器的输入参数结构体
//我们只需要每个顶点的位置与对应的法向量
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
//定义顶点着色的输出结构体/片段着色的输入结构体
//已经计算好的颜色
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
//顶点着色器
vertexOutput vert (vertexInput input) {
vertexOutput output;
//对象坐标系到世界坐标系的变换矩阵
//_Object2World与_World2Object均为unity提供的内置uniform参数
float4x4 modelMatrix = _Object2World;
//世界坐标系到对象坐标系的变换矩阵
float4x4 modelMatrixInverse = _World2Object;
//计算对象坐标系中的顶点法向量的单位向量
//将mesh传递过来的顶点法向量与模型-->对象坐标系矩阵相乘得到对象坐标系中的法向量
//然后单位化
float3 normalDirection = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse)));
//计算入射向量的单位向量
float3 lightDirection = normalize(float3(_WorldSpaceLightPos0));
//计算反射后的颜色
//先将光源颜色与材料颜色向量相乘
//再乘以上文提到的max(0,cos∠(N,L))
float3 diffuseReflection=float3(_LightColor0) * float3(_Color)* max(0.0, dot(normalDirection, lightDirection));
//上面计算的是RGB颜色,差个A,补充一维就可以传递给片段着色器了
output.col=float4(diffuseReflection,1);
//国际惯例,顶点变化三步曲,这个例子中可写可不写
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
//片段着色器,老规矩,把顶点着色器的输出参数作为片段着色器的输入参数
float4 frag(vertexOutput input): COLOR
{
return input.col;
}
ENDCG
}
Pass{
//其余的像素光所在的反射通道标记为ForwardAdd
Tags {"LightMode" = "ForwardAdd"}
//此通道的片段着色器输出颜色时帧缓存已经有了颜色,所以需要混合
//混合模式为1比1
Blend One One
CGPROGRAM
// Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs.
//#pragma exclude_renderers gles
//定义顶点着色器与片段着色器入口
#pragma vertex vert
#pragma fragment frag
//获取property中定义的材料颜色
uniform float4 _Color;
// 光源的位置或者方向
//uniform float4 _WorldSpaceLightPos0;
// 光源的颜色 (from "Lighting.cginc")
uniform float4 _LightColor0;
//定义顶点着色器的输入参数结构体
//我们只需要每个顶点的位置与对应的法向量
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
//定义顶点着色的输出结构体/片段着色的输入结构体
//已经计算好的颜色
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
};
//顶点着色器
vertexOutput vert (vertexInput input) {
vertexOutput output;
//对象坐标系到世界坐标系的变换矩阵
//_Object2World与_World2Object均为unity提供的内置uniform参数
float4x4 modelMatrix = _Object2World;
//世界坐标系到对象坐标系的变换矩阵
float4x4 modelMatrixInverse = _World2Object;
//计算对象坐标系中的顶点法向量的单位向量
//将mesh传递过来的顶点法向量与模型-->对象坐标系矩阵相乘得到对象坐标系中的法向量
//然后单位化
float3 normalDirection = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse)));
//计算入射向量的单位向量
float3 lightDirection = normalize(float3(_WorldSpaceLightPos0));
//计算反射后的颜色
//先将光源颜色与材料颜色向量相乘
//再乘以上文提到的max(0,cos∠(N,L))
float3 diffuseReflection=float3(_LightColor0) * float3(_Color)* max(0.0, dot(normalDirection, lightDirection));
//上面计算的是RGB颜色,差个A,补充一维就可以传递给片段着色器了
output.col=float4(diffuseReflection,1);
//国际惯例,顶点变化三步曲,这个例子中可写可不写
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
}
//片段着色器,老规矩,把顶点着色器的输出参数作为片段着色器的输入参数
float4 frag(vertexOutput input): COLOR
{
return input.col;
}
ENDCG
}
}
}
解读Unity中的CG编写Shader系列八(多光源漫反射)的更多相关文章
- [转]解读Unity中的CG编写Shader系列8——多光源漫反射
前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下我们的物体表面的漫反射强度如何叠加在一起呢?前文打的tag "LightMod ...
- 解读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)和前面剪裁.后 ...
随机推荐
- Orchard源码分析(4):Orchard.Environment.OrchardStarter类
概述 OrchardStarter类是个静态类,主要作用是配置Autofac容器以及创建IOrchardHost(DefaultOrchardHost)对象,分别对应CreateHost和Create ...
- Selenium 代码收集
[转载]使用Selenium2测试含有iframe的Ajax网页 原文地址:http://www.cnblogs.com/hexin0614/archive/2012/03/24/2415670.h ...
- [转] 安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2出现0x80072f8a未指定的错误
原文地址:安装DotNetCore.1.0.1-VS2015Tools.Preview2.0.2出现0x80072f8a未指定的错误 最近DotNetCore更新到了1.0.1,Azure tools ...
- 数字格式化函数:Highcharts.numberFormat()
(转)数字格式化函数:Highcharts.numberFormat() 一.函数说明 该函数用于图表中数值的格式化,常见用途有数值精度控制.小数点符.千位符显示控制等. 二.函数使用 1.函 ...
- django view
当请求一个页面时,Django 创建一个包含有关请求数据的 HttpRequest 对象,并将它作为第一个参数传给视图函数,每个视图函数处理完相应逻辑后返回一个 HttpResponse 对象,Htt ...
- ACM_1 大数求和
/*1 *2014.11.18 *大数求和 */ #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <strin ...
- svn搬移到gitlab及使用
svn是一款非常简便,易用的源代码管理工具,用了这么多年,对它情有独钟.都说习惯最难改,那为何要搬移到gitlab上呢? 喜欢尝试新东西,前提还是git比较强大,svn有的它都有,svn没有的它也有. ...
- C++ Singleton模式
地址:http://www.cppblog.com/dyj057/archive/2005/09/20/346.html Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却 ...
- FineUI第十二天---锚点布局
锚点布局的典型结构: <x:Panel Layout="Anchor" runat="server"> <Items ...
- Fedora 25 Alpha版本今天发布啦
时隔Fedora 24发布后的3个月,Fedora项目团队非常开心的宣布任何感兴趣的用户都能下载和测试即将到来的Fedora 25操作系统的Alpha预发布版本,在Fedora 25 Alpha里程碑 ...