unity surface shader 1
Unity ShaderLib : CGPROGRAM ENDCG之间是CG代码,之外的代码功能都由ShaderLib提供,CG中的一些方法比如tex2D(...)也是ShaderLib对CG进行了封装
SurfaceShader全部函数Demo
Shader "Nafio/BaseSurf" { Properties
{
_MainTex("_MainTex",2D) = "white" {}
_Color("Color",Color) = (1,1,1,1)
} SubShader
{
Tags{"RenderType" = "Opaque"}
LOD 200
CGPROGRAM
#pragma surface surf CustomLambert vertex:vert finalcolor:final
sampler2D _MainTex;
fixed4 _Color;
struct Input{
half2 uv_MainTex;
float4 vertcolor;
}; void vert(inout appdata_full v,out Input IN)
{
UNITY_INITIALIZE_OUTPUT(Input,IN);//不初始化会报错..
IN.vertcolor = v.color;
} void surf(Input IN,inout SurfaceOutput o)
{
half4 c = tex2D(_MainTex,IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
} inline half4 LightingCustomLambert(SurfaceOutput s,half3 LightDir,half atten)
{
half nl = max(0,dot(s.Normal,LightDir));
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (nl * atten * 2);
c.a = s.Albedo;
return c;
} void final(Input IN,SurfaceOutput s,inout fixed4 c)
{
c = c * 0.9+0.1;
} ENDCG
}
FallBack "Diffuse" }
普通漫反射
Shader "Nafio/NDiffuse" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}//变量名_MainText,显示名Base(RGB),类型2D,默认值白色white,最后{}里面可以放一些控制参数
}
SubShader {
Tags { "RenderType"="Opaque" } //处理不透明物体用这段shader
LOD 200 //LOD 200如果Unity中配置的Lod小于这个值,那么这段shader就不起作用,unity中maxLod默认配的0,就是所有数值都起作用
//另外可以用代码来制定具体shader的LOD限制
CGPROGRAM //CG开始
#pragma surface surf Lambert //surface使用surface shader surf表面shader函数名 Lambert使用的光照模型为Lambert sampler2D _MainTex; //定义一张2d图片(就是从属性中的_MainTex链接过来的,否则cg无法使用) struct Input {
float2 uv_MainTex //取MainTex的uv
}; void surf (Input IN, inout SurfaceOutput o) { //IN是向表面着色器处理函数输入的函数,SurfaceOutput是向光照处理函数输出的参数
half4 c = tex2D (_MainTex, IN.uv_MainTex); //获取—_MainText固定uv点的颜色出来
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"//如果当前shader不能正确执行,回调默认shader
}
注意:这里surf函数执行的是执行光照前的操作
使用surf处理法线贴图
Shader "Custom/Normal Mapping" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Bump ("Bump", 2D) = "bump" {} //法线贴图
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Lambert sampler2D _MainTex;
sampler2D _Bump; struct Input {
float2 uv_MainTex;
float2 uv_Bump;
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex); o.Normal = UnpackNormal(tex2D(_Bump, IN.uv_Bump); //获取法线信息 o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
加入自定义光照模型
Shader "Nafio/NDiffuseLight" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf CustomDiffuse //CustomDiffuse自定义光照模型函数名 sampler2D _MainTex; struct Input {
float2 uv_MainTex;
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
} inline float4 LightingCustomDiffuse (SurfaceOutput s, fixed3 lightDir, fixed atten) { //LightingCustomDiffuse名称与上面定义有关,s是surf函数的输出,lightDir光方向,atten衰减系数
float difLight = max(0, dot (s.Normal, lightDir));
float4 col;
col.rgb = s.Albedo * _LightColor0.rgb * (difLight * atten * 2);
col.a = s.Alpha;
return col;
}
ENDCG
}
FallBack "Diffuse"
}
UV滚动
Shader "Nafio/NScrollTexture" {
Properties {
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_ScrollXSpeed ("XSpeed",Range(0,10)) = 2
_ScrollYSpeed ("YSpeed",Range(0,10)) = 2
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Lambert fixed4 _MainTint;//fixed为定点数,可以模拟浮点数,特点计算速度快
sampler2D _MainTex;
fixed _ScrollXSpeed;
fixed _ScrollYSpeed; struct Input {
float2 uv_MainTex;
}; void surf (Input IN, inout SurfaceOutput o) { fixed2 scrollUV = IN.uv_MainTex;
fixed xScrollValue = _ScrollXSpeed * _Time;//这里的shader中的time跟unity中的Time类似
fixed yScrollValue = _ScrollYSpeed * _Time;
scrollUV += fixed2(xScrollValue,yScrollValue); half4 c = tex2D (_MainTex, scrollUV);
o.Albedo = c.rgb * _MainTint;//_MainTint可有可无,不影响滚动,只是一个附加色
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
unity中默认的BlinnPhong镜面反射
Shader "Nafio/NDefaultSpec" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint ("Diffuse Tint",Color) = (1,1,1,1)
_SpecColor ("Specular Color",Color) = (1,1,1,1)
_SpecPower("Specular Color",Range(0,1)) = 0.5
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf BlinnPhong sampler2D _MainTex;
float _SpecPower;
float4 _MainTint; struct Input {
float2 uv_MainTex;
}; void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex)*_MainTint;
o.Specular = _SpecPower;
o.Gloss = 1.0;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
unity中默认的Phong
Shader "Nafio/NPhong" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint("Diffuse Tint",Color) = (1,1,1,1)
_SpecularColor("Specular Color",Color) = (1,1,1,1)
_SpecularPower("Specular Power",Range(0,30)) = 1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Phong sampler2D _MainTex;
float4 _MainTint;//nafio 这些变量为何不用fixed:fixed范围-2 - 2
float4 _SpecularColor;
float _SpecularPower; struct Input {
float2 uv_MainTex;//nafio 为何只有uv在这里传:这是input用来从vertex shader向fragram shader传递数据,需要什么定义什么
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
} //nafio phong光照公式
//入射光反射向量的单位向量 r = 2*(n点乘l)*n
//反射光和视角方向的 差别用dot(reflectionVector,viewDir)表示
//镜面反射分量强度 pow(max(0,dot(reflectionVector,viewDir)),_SpecularPower);
//最后结果是漫反射结果+镜面反射结果
//总结phong实际计算公式就是 pow(r点乘v,材质高光系数)
//而bilnnPhong实际就是这个公式的简化 pow(n点乘h,材质高光系数),所以bilnnPhong更快
inline half4 LightingPhong(SurfaceOutput s,half3 lightDir,half3 viewDir,fixed atten){
float diff = max(0,dot(s.Normal,lightDir));
float3 reflectionVector = normalize(2.0 * s.Normal * diff - lightDir);
float spec = pow(max(0,dot(reflectionVector,viewDir)),_SpecularPower);
float3 finalSpec = _SpecularColor.rgb * spec;
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten) + (_LightColor0.rgb * finalSpec);
c.a = 1;
return c;
} ENDCG
}
FallBack "Diffuse"
}
自定义BlinnPhong
Shader "Nafio/NBlinn" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_MainTint("Diffuse Tint",Color) = (1,1,1,1)
_SpecularPower("Specular Power",Range(0.1,200)) = 1
_SpecularColor("Specular Color",Color) = (1,1,1,1)
} SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf CustomBlinnPhong sampler2D _MainTex;
float4 _MainTint;
float4 _SpecularColor;
float _SpecularPower; struct Input {
float2 uv_MainTex;
}; void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
} inline half4 LightingCustomBlinnPhong(SurfaceOutput s,half3 lightDir,half3 viewDir,fixed atten){
fixed3 halfVector = normalize(lightDir + viewDir);
fixed diff = max(0,dot(s.Normal,lightDir));
fixed nh = max(0,dot(s.Normal,halfVector));
half spec = pow(nh,_SpecularPower);
half4 c;
c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten) +(_LightColor0.rgb * _SpecularColor.rgb * spec);
c.a = 1;
return c;
} ENDCG
}
FallBack "Diffuse"
}
Lit Sphere
Shader "Custom/LitSphere" {
Properties {
_MainTint ("Diffuse Tint", Color) = (1,1,1,1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 CGPROGRAM
#pragma surface surf Unlit vertex:vert float4 _MainTint;
sampler2D _MainTex;
sampler2D _NormalMap; inline half4 LightingUnlit (SurfaceOutput s, fixed3 lightDir, fixed atten)
{
half4 c = half4(1,1,1,1);
c.rgb = s.Albedo;//直接使用了surf中的颜色结果(从贴图里得到的假光照),没计算真正的光照
c.a = s.Alpha;
return c;
} struct Input {
float2 uv_MainTex;
float2 uv_NormalMap;
float3 tan1;
float3 tan2;
}; void vert (inout appdata_full v, out Input o)
{
UNITY_INITIALIZE_OUTPUT(Input,o);//Input类型变量o 置0,如果不是HSHL这句就是空的宏什么都不做
TANGENT_SPACE_ROTATION; //产生rotation这个矩阵并赋值的一段宏
o.tan1 = mul(rotation, UNITY_MATRIX_IT_MV[0].xyz); //把观察坐标下的x轴转换到切向坐标系
o.tan2 = mul(rotation, UNITY_MATRIX_IT_MV[1].xyz); //把观察坐标下的y轴转换到切向坐标系
} void surf (Input IN, inout SurfaceOutput o)
{
float3 normals = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap));
o.Normal = normals;
float2 litSphereUV;
litSphereUV.x = dot(IN.tan1, o.Normal);//tan1是从观察系被转换到切向坐标的x轴,Normal是法线贴图中法向量,法向量向x轴投,得到u
litSphereUV.y = dot(IN.tan2, o.Normal); //tan2是从观察系被转换到切向坐标的y轴,Normal是法线贴图中法向量,法向量向y轴投,得到v //这里注意一点,上面dot的计算是因为用的是一张做好光照的贴图,简单说就是在这个<贴图中光方向是固定的,
//如果法线朝向接近光源的位置,就取图上更亮的一点,
//不好理解的是法线向观察系x,y坐标投影来决定使用图(含有光照方向)上哪一点 half4 c = tex2D (_MainTex, litSphereUV*0.5+0.5);//*0.5+0.5是因为,dot的值是-1~1,而uv是0-1做了一下转换
o.Albedo = c.rgb * _MainTint;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
TANGENT_SPACE_ROTATION;
o.tan1 = mul(rotation, UNITY_MATRIX_IT_MV[0].xyz);
TANGENT_SPACE_ROTATION
// Declares 3x3 matrix 'rotation', filled with tangent space basis
#define TANGENT_SPACE_ROTATION \
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w; \
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal )
这句作用是把观察坐标中的x轴转换到切向坐标,为了了解这句,需要趟几个坑
mul(_Object2World,v.vertex)
如果换成行向量就是
mul(v.vertex,transpose(_Object2World))
注意Unity默认一般用上面的写法,所以unity内部用的应该是列向量,_Object2World,_World2Object这类矩阵也都是跟列向量乘的
unity没提供从观察系直接转换到切向坐标的矩阵,这里需要先从观察系转换到模型坐标
具体方法就是
mul(UNITY_MATRIX_VM, float3(1, 0, 0)) 等同于
mul(float3(1,0,0),transpose(UNITY_MATRIX_VM))
而unity中并没有UNITY_MATRIX_VM(观察到模型的变换矩阵),但是有UNITY_MATRIX_IT_MV(模型到观察的逆转置),进一步变化
mul(float3(1,0,0), (float3x3)UNITY_MATRIX_IT_MV)) 等同于
UNITY_MATRIX_IT_MV[0].xyz
其中1,0,0是观察系中的x轴,UNITY_MATRIX_IT_MV[0].xyz代表观察系中x轴在模型坐标系中的向量表示
法线的空间转换比较特殊,正常向量转换直接乘相应矩阵,但法向量无论向哪个空间转换
float4 worldV = mul(_Object2World,v.vertex);
float4 worldNorm = mul(v.normal, _World2Object);
float4 worldNorm = mul(transpose(_World2Object), v.normal);
这里注意_World2Object 就是_Object2World的逆矩阵
litSphereUV.x = dot(IN.tan1, o.Normal); 这个计算方式 跟贴图相关
unity surface shader 1的更多相关文章
- unity, surface shader access world position and localposition
一,surface shader中访问worldposition 在surface shader中访问世界坐标,只需在Input结构体中声明float3 worldPos即可,如下: struct ...
- Unity surface shader 2
UV滚动 Shader "Nafio/ScrollUV" { Properties { _Tex("T",2D) = "white" {} ...
- 【Unity Shaders】初探Surface Shader背后的机制
转载请注明出处:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的 ...
- Unity Shader (三)Surface Shader机制
转自:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的机制一直是 ...
- Unity Shader——Writing Surface Shaders(3)——Surface Shader Lighting Examples
Surface Shader 光照例子 这里有一些自定义光照模型和Surface Shaders的例子.通常的Surface Shader例子在这里. 由于延迟光照在某些自定义的逐材质光照模型中表现得 ...
- 【Unity Shaders】Shader学习资源和Surface Shader概述
写在前面 写这篇文章的时候,我断断续续学习Unity Shader半年了,其实还是个门外汉.我也能体会很多童鞋那种想要学好Shader却无从下手的感觉.在这个期间,我找到一些学习Shader的教程以及 ...
- 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Unity Shader——Writing Surface Shaders(1)——Surface Shader Examples
这里有Surface Shader的一些例子.下面的这些例子关注使用内建的光照模型:关于如何使用自定义光照模型的例子参见Surface Shader Lighting Examples. 简单 我们将 ...
- unity, unlit surface shader (texColor only surface shader)
要实现双面透明无光照只有纹理色的surface shader. 错误的写法:(导致带有曝光) Shader "Custom/doubleFaceTranspTexColor" { ...
随机推荐
- Sping框架概述
一.什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,i ...
- ajax json html 结合
<table id="datas" border="1" cellspacing="0" style="border-col ...
- A桶中有多少水?
如果你能算出桶中有多少水,我便许你下山去玩.有一天,老和尚让小和尚将A桶的水挑到B桶去,可是小和尚却想下山玩,不愿意挑水,老和尚便说:”如果你能够根据我的提示算出A桶中有多少升水,我便许你下山去玩.” ...
- Activity和ListActivity的区别
http://book.51cto.com/art/201007/212051.htm
- php钩子技术
通过对钩子技术的理解,下面把自己对钩子技术的总结如下:"钩子就是在调用php核心功能代码的同时可以在不修改核心代码的同时,更改核心代码的行为";具体模拟实现如下 /** * php ...
- UVA10870 Recurrences —— 矩阵快速幂
题目链接:https://vjudge.net/problem/UVA-10870 题意: 典型的矩阵快速幂的运用.比一般的斐波那契数推导式多了几项而已. 代码如下: #include <bit ...
- 手写Future模式
根据前面我所说的Futrue模式,手写一个: 分别对应的Java代码,大家拿来参考: package FutureTest; //公共data数据接口 public abstract class Da ...
- ansible快速学习
推荐文献: 表述的很不错, http://www.mamicode.com/info-detail-1428476.html 附加参考: http://laowafang.blog.51cto.com ...
- PYTHON 爬虫笔记一:爬虫基本原理梳理
知识点一:爬虫的基本原理梳理 一.什么是爬虫? 请求网站并提取数据的自动化程序 二.爬虫的基本流程 1:向服务器发起请求 通过HTTP库向目标站点发起请求,即发送一个Request,请求可以包含额外的 ...
- cookie(点心的意思)服务器给客户端的点心
他是用户访问web服务器时,服务器在用户硬盘上存放的信息,好像是服务器给客户端的“点心”.比如:是否记录用户名密码.其中,A服务器不允许访问B服务器存在客户端的cookie 一个cookie包含一对k ...