Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples
Surface Shader 光照例子
这里有一些自定义光照模型和Surface Shaders的例子。通常的Surface Shader例子在这里。
由于延迟光照在某些自定义的逐材质光照模型中表现得并不好,在下面大多数例子中,我们让shader只编译到正向渲染中。
漫反射(Diffuse)
让我们以使用内建Lambert光照模型的shader作为开始吧!
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
下面是使用一张纹理贴图和不使用一张真实的纹理贴图的样子(此场景中有一个方向光)

现在,我们来做个完全一样的,但是使用我们自己的光照模型,而不是内建Lambert光照模型。Surface Shader光照模型仅是一些我们需要编写的函数。这里有一个简单的Lambert光照模型。注意到只有CGPROGRAM部分发生了改变,周边的shader代码是完全一样的:
Shader "Example/Diffuse Texture" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf SimpleLambert
half4 LightingSimpleLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * );
c.a = s.Alpha;
return c;
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
所以我们的简单漫反射光照模型就是LightingSimpleLambert 函数。它通过计算表面法线和光线方向的点积来计算光照,然后应用光照衰减和颜色。
环绕漫反射(Diffuse Wrap)
这里是环绕漫反射——漫反射光照的修改版,即照明环绕在物体的边缘。它对用来仿照次表面散射效果很有用。因为只是CGPROGRAM 部分发生了改变,老生常谈一次,周边的shader代码就省略了:
...ShaderLab code...
CGPROGRAM
#pragma surface surf WrapLambert half4 LightingWrapLambert (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half diff = NdotL * 0.5 + 0.5;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * );
c.a = s.Alpha;
return c;
} struct Input {
float2 uv_MainTex;
}; sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...
卡通渐变(Toon Ramp)
下面是一个"渐变(Ramp)"光照模型。它使用一张渐变纹理来定义表面怎样对光线和法线的夹角做出反应。这能用来实现多种效果,包括卡通光照。
...ShaderLab code...
CGPROGRAM
#pragma surface surf Ramp sampler2D _Ramp; half4 LightingRamp (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half diff = NdotL * 0.5 + 0.5;
half3 ramp = tex2D (_Ramp, float2(diff)).rgb;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * ramp * (atten * );
c.a = s.Alpha;
return c;
} struct Input {
float2 uv_MainTex;
}; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...


简单镜面(Simple Specular)
下面是一个简单镜面光照模型。这对于内置的BlinnPhong实际所做的内容来说非常简单。我们把它放在这来说明它是如何工作的。
...ShaderLab code...
CGPROGRAM
#pragma surface surf SimpleSpecular half4 LightingSimpleSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten) {
half3 h = normalize (lightDir + viewDir); half diff = max (, dot (s.Normal, lightDir)); float nh = max (, dot (s.Normal, h));
float spec = pow (nh, 48.0); half4 c;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * spec) * (atten * );
c.a = s.Alpha;
return c;
} struct Input {
float2 uv_MainTex;
}; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
...ShaderLab code...
解码光照贴图(Decoding Lightmaps)
我们将以这样一个shader作为开始:它模仿内置的光照贴图解码工作,使用Unity自带的DecodeLightmap函数解码lightmap中储存的数据信息,以及使用自带的UNITY_DIRBASIS宏定义方向光照贴图(Directional lightmap)的基本向量:
Shader "Example/Standard Lightmap Decoding" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Standard
half4 LightingStandard (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * );
c.a = s.Alpha;
return c;
}
inline fixed4 LightingStandard_SingleLightmap (SurfaceOutput s, fixed4 color) {
half3 lm = DecodeLightmap (color);
return fixed4(lm, );
}
inline fixed4 LightingStandard_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
half3 lm = lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade);
return fixed4(lm, );
}
inline fixed4 LightingStandard_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {
UNITY_DIRBASIS
half3 lm = DecodeLightmap (color);
half3 scalePerBasisVector = DecodeLightmap (scale);
if (surfFuncWritesNormal)
{
half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));
lm *= dot (normalInRnmBasis, scalePerBasisVector);
}
return fixed4(lm, );
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
现在,让我们为光照贴图中储存的光添加些色调映射(tone mapping):
Shader "Example/Tonemapped Lightmap Decoding" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Gain ("Lightmap tone-mapping Gain", Float) =
_Knee ("Lightmap tone-mapping Knee", Float) = 0.5
_Compress ("Lightmap tone-mapping Compress", Float) = 0.33
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Tonemapped
half4 LightingTonemapped (SurfaceOutput s, half3 lightDir, half atten) {
half NdotL = dot (s.Normal, lightDir);
half4 c; c.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten * ); c.a = s.Alpha;
return c;
}
half _Gain;
half _Knee;
half _Compress;
inline half3 TonemapLight (half3 i) {
i *= _Gain;
return (i > _Knee)? (((i - _Knee)*_Compress)+_Knee): i;
}
inline fixed4 LightingTonemapped_SingleLightmap (SurfaceOutput s, fixed4 color) {
half3 lm = TonemapLight(DecodeLightmap (color));
return fixed4(lm, );
}
inline fixed4 LightingTonemapped_DualLightmap (SurfaceOutput s, fixed4 totalColor, fixed4 indirectOnlyColor, half indirectFade) {
half3 lm = TonemapLight(lerp (DecodeLightmap (indirectOnlyColor), DecodeLightmap (totalColor), indirectFade));
return fixed4(lm, );
}
inline fixed4 LightingTonemapped_StandardLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal) {
UNITY_DIRBASIS
half3 lm = TonemapLight(DecodeLightmap (color));
half3 scalePerBasisVector = DecodeLightmap (scale);
if (surfFuncWritesNormal)
{
half3 normalInRnmBasis = saturate (mul (unity_DirBasis, s.Normal));
lm *= dot (normalInRnmBasis, scalePerBasisVector);
}
return fixed4(lm, );
}
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples的更多相关文章
- Unity Shader——Writing Surface Shaders(1)——Surface Shader Examples
这里有Surface Shader的一些例子.下面的这些例子关注使用内建的光照模型:关于如何使用自定义光照模型的例子参见Surface Shader Lighting Examples. 简单 我们将 ...
- Unity Shader——Writing Surface Shaders(2)——Custom Lighting models in Surface Shaders
Surface Shader中的自定义光照模型 当你在编写 Surface Shaders 时,是在描述一个表面的属性(反射颜色.法线……),而且光的交互过程是由一个光照模型来计算的.内建的光照模型有 ...
- Unity Shader——Writing Surface Shaders(0)
从今天起,开始翻译Unity关于shader的官方文档.翻译水平比较一般,目的主要是通过翻译来提升对shader的见解,也让其他人更容易的了解shader.以下开始正文内容: 编写Surface Sh ...
- Writing Surface Shaders
[Writing Surface Shaders] Writing shaders that interact with lighting is complex. There are differen ...
- Unity Shaders Vertex & Fragment Shader入门
http://blog.csdn.net/candycat1992/article/details/40212735 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Sha ...
- Unity 的“Vertex Lit Rendering path“中 shader Pass 的注意事项
"MADFINGER/Environment/Unlit (Supports Lightmap)"是 ShadowGun 示例中最简单的 shader 了,如下: // Unlit ...
- 【Unity Shader实战】卡通风格的Shader(一)
写在前面 本系列其他文章: 卡通风格的Shader(二) 呜,其实很早就看到了这类Shader,实现方法很多,效果也有些许不一样.从这篇开始,陆续学习一下接触到的卡通类型Shader的编写. 本篇的最 ...
- Unity加载模块深度解析(Shader)
作者:张鑫链接:https://zhuanlan.zhihu.com/p/21949663来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 接上一篇 加载模块深度解析(二 ...
- Unity3D Shader官方教程翻译(十九)----Shader语法,编写表面着色器
Writing Surface Shaders Writing shaders that interact with lighting is complex. There are different ...
随机推荐
- 转!!mysql order by 中文排序
1. 在MySQL中,我们经常会对一个字段进行排序查询,但进行中文排序和查找的时候,对汉字的排序和查找结果往往都是错误的. 这种情况在MySQL的很多版本中都存在. 如果这个问题不解决,那么MySQL ...
- [转载]Eclipse提示No java virtual machine
第一次运行Eclipse,经常会提示下面的问题:... No java virtual machine was found after searching the follwing location ...
- Django1.9开发博客(6)- 模板继承
模板继承就是网站的多个页面可以共享同一个页面布局或者是页面的某几个部分的内容.通过这种方式你就需要在每个页面复制粘贴同样的代码了. 如果你想改变页面某个公共部分,你不需要每个页面的去修改,只需要修改一 ...
- css 浮动
1. 浮动 浮动是css的布局功能,在CSS中,包括div在内的任何元素都可以浮动的方式显示.它能够改变页面中对象的前后流动顺序.浮动元素会脱离文档流,不占据空间.浮动元素可以左右移动,直到碰到包含它 ...
- 在 Vultr VPS 中 以 Debian 8 i386 (jessie) 为 操作系统 平台 手动 搭建 PPTP VPN 全过程
更新服务器并安装 PPTP 服务 apt-get update apt-get upgrade apt-get install pptpd 编辑 /etc/pptpd.conf 找到 #locali ...
- 【转】ora-00031:session marked for kill处理oracle中杀不掉的锁
一些ORACLE中的进程被杀掉后,状态被置为"killed",但是锁定的资源很长时间不释放,有时实在没办法,只好重启数据库.现在提供一种方法解决这种问题,那就是在ORACLE中杀不 ...
- Jmeter—3 http请求—content-type与参数
本文讲三种content-type以及在Jmeter中对应的参数输入方式 第一部分:目前工作中涉及到的content-type 有三种: content-type:在Request Headers里, ...
- MySQL数据库2 - 登录MySQL及数据库管理
一. 登录数据库 1.使用命令窗口登录MySQL 启动Mysql服务 -> 打开命令窗口 -> 输入登录密码 具体步骤:开始菜单 - 控制面板 - 管理工具 - 服务 - Mysql56( ...
- 如何在Eclipse中设置默认的JSP文件头部编码
如何在Eclipse中设置默认的JSP文件头部编码 一般,我们为了以后在导入和导出程序的时候(特别是项目较大,文件多)一般都默认文件编码格式为UTF-8 如果你通常都是通过Eclipse来编写程序,那 ...
- SAP 增强-出口选找方法-全部
■ SAP 中如何寻找增强 方法一:利用TCODE寻找增强(第二代的增强) 执行一个程序(源代码后附),在选择屏幕处输入你所需要增强的程序TCODE,执行後,就会出现一个列表,那里就有关于如何增强这个 ...
