Shader "AP1/L03/FlatCol" {
Properties {
//材质面板
}
SubShader {
Tags {
"RenderType"="Opaque"
}
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase" //Pass标签
}
CGPROGRAM //包围CG代码
#pragma vertex vert //定义顶点和片元着色器
#pragma fragment frag
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
// 输入结构
struct VertexInput {
float4 vertex : POSITION; // 将模型的顶点信息输入进来
};
// 输出结构
struct VertexOutput {
float4 pos : SV_POSITION; // 由模型顶点信息换算而来的顶点屏幕位置
};
// 输入结构>>>顶点Shader>>>输出结构
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0; // 新建一个输出结构
o.pos = UnityObjectToClipPos( v.vertex ); //变换顶点信息并将其塞给输出结构
return o; // 将输出结构 输出
}
// 输出结构>>>像素
float4 frag(VertexOutput i) : COLOR {
return float4(0.0, 1.0, 0.0, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
float4 frag(VertexOutput i) : COLOR
{
float3 nDir = i.nDirWS;
float3 lDir = _WorldSpaceLightPos0.xyz;
float nDotl = dot(nDir,lDir); //
float lambert = max(0.0,nDotl);
return float4(lambert,lambert,lambert,1.0);
}
float lambert = nDotl*0.5+0.5;
Lambert Half Lambert Ramptex作业
思路: 以半兰伯特模型构造uv坐标采样Ramptex(Ramptex贴图:1. 3阶明度,过渡卡硬 2.暗部色相变化,少明度变化)
1. 玉石效果
2. 像素点效果
3. SSSLut效果
float3 rDir = reflect(-lDir,nDir);
float rDotv = dot(rDir,vDir);
float phong = pow(max(0.0,rDotv),_SpecularPow);
float3 finaRGB = _MainCol * lambert + phong;
float3 hDir = normalize( vDir + lDir );
float nDoth = dot(nDir,hDir);
float blinnphong = pow(max(0.0,nDoth),_SpecularPow);
Phong Blinn-Phong
shader forge:
代码:
Shader "Unlit/13_OldSchoolPlus"
{
Properties
{
_BaseCol ("BaseCol",color) = (1.0, 1.0, 1.0, 1.0)
_SpecularPow ("SpecularPow", range(1,90)) = 30
_LightCol ("LightCol",color) = (1.0, 1.0, 1.0, 1.0)
_Occlusion ("Occlusion", 2D) = "white" {}
_EnvUpCol ("EnvUpCol",color) = (1.0, 1.0, 1.0, 1.0)
_EnvSideCol ("EnvSideCol",color) = (1.0, 1.0, 1.0, 1.0)
_EnvDownCol ("EnvDownCol",color) = (1.0, 1.0, 1.0, 1.0)
_EnvColPow ("EnvColPow", range(0,1)) = 0.2
}
SubShader
{
Tags { "LightMode"="ForwardBase" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "AutoLight.cginc"//投影头文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//输入参数
uniform float3 _BaseCol;
uniform float _SpecularPow;
uniform float _EnvColPow;
uniform float3 _LightCol;
uniform float3 _EnvUpCol;
uniform float3 _EnvSideCol;
uniform float3 _EnvDownCol;
uniform sampler2D _Occlusion;
//输入结构
struct VertexInput{
float4 vertex : POSITION;
float4 normal : NORMAL;
float2 texcoord0: TEXCOORD0; //将模型uv信息输入进0通道
};
//输出结构
struct VertexOutput{
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 posWorld : TEXCOORD1;
float3 normalDir : TEXCOORD2;//追加uv信息用于像素shader采样贴图
LIGHTING_COORDS(3,4)//投影
};
//输入结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v){
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.posWorld = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = v.texcoord0;
o.normalDir = UnityObjectToWorldNormal(v.normal);
TRANSFER_VERTEX_TO_FRAGMENT(o)//投影
return o;
}
//输出结构>>>像素
float4 frag(VertexOutput i) : color{
//环境光
//准备向量
float3 nDir = i.normalDir;
//计算各部分遮罩
float upMask = max(0.0, nDir.g);
float downMask = max(0.0, -nDir.g);
float sideMask = 1.0 - upMask - downMask;
//混合环境色
float3 envCol = _EnvColPow*(_EnvUpCol*upMask + _EnvSideCol*sideMask + _EnvDownCol*downMask);
//采样AO贴图
float occlusion = tex2D(_Occlusion , i.uv0);
//计算环境光照
float3 envLighting = envCol * occlusion;
//兰伯特光照模型
float3 lDir = _WorldSpaceLightPos0.xyz;
float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz);
float3 vRDir = reflect( -vDir, nDir );
float nDotl = dot(nDir,lDir);
float vRDotl = dot(lDir,vRDir); //点积得到的是标量
//光照模型
float lambert = max(0.0,nDotl);
float phong = pow(max(0.0,vRDotl),_SpecularPow);
//投影
float attenuation = LIGHT_ATTENUATION(i);
float3 finaRGB = attenuation*(_LightCol*(_BaseCol * lambert + phong))+envLighting;
return float4(finaRGB,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
因为法线贴图里面是切向空间的法线信息,而我们实际需要的是世界空间的法线信息,为此我们需要一个桥梁来将切向空间的法线信息转化会世界空间的法线信息,这个桥梁就是TBN矩阵。
https://zhuanlan.zhihu.com/p/412555049
代码:
Shader "14_NormalMap"
{
Properties
{
_normalMap ("normalMap",2D) = "bump" {} //默认为bump
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
uniform sampler2D _normalMap;
struct VertexInput
{
float4 vertex: POSITION;
float4 normal: NORMAL;
float4 tangent: TANGENT; //
float2 uv0: TEXCOORD0;
};
struct VertexOutput
{
float4 pos: SV_POSITION;
float2 uv0: TEXCOORD0;
float3 nDirWS: TEXCOORD1;
float3 tDirWS : TEXCOORD2;
float3 bDirWS : TEXCOORD3;
};
VertexOutput vert (VertexInput v)
{
VertexOutput o = (VertexOutput)0; //新建一个输出结构
o.pos = UnityObjectToClipPos( v.vertex ); //变换顶点信息,从物体变换成世界坐标系
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal( v.normal ); //变换法线信息,同上
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4( v.tangent.xyz, 0.0 )).xyz);
o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS)* v.tangent.w); //w确定方向
return o;
}
float4 frag(VertexOutput i) : COLOR
{
float3 nDirTS = UnpackNormal(tex2D(_normalMap, i.uv0));
float3x3 TBN = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
float3 nDir = normalize(mul(nDirTS, TBN));
float3 lDir = _WorldSpaceLightPos0.xyz;
float nDotl = dot(nDir,lDir);
float lambert = max(0.0,nDotl);
return float4(lambert,lambert,lambert,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
视线垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显。如果你看向一个圆球,那圆球中心的反射较弱,靠近边缘较强。不过这种过度关系被折射率影响。
在真实世界中,除了金属之外,其它物质均有不同程度的“菲涅尔效应”。
Fresnel = pow(1-ndotv,powVal)
• ldotv:理解为光从眼睛发出时的Lambert; 中间亮,边缘暗;
• 1-ldotv:黑白反相,中间暗,边缘亮;
• power:套一个power控制边缘亮的范围;
Material Capture(材质捕捉),将光源、材质信息离线烘焙成一张材质球放在贴图上,渲染时候直接拿来用,通过计算将MatCap的纹理信息映射到模型上。
代码:
Shader "Unlit/15_MatCap"
{
Properties
{
_NormalMap ("法线贴图", 2D) = "bump" {}
_MatCap ("MatCap",2D) = "grey" {}
_FresnelPow ("菲涅尔次幂", Range(0,10)) = 1
_EnvSpecInt ("环境镜面反射强度", Range(0,5))=1
}
SubShader
{
Tags { "LightMode"="ForwardBase" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "AutoLight.cginc"//投影头文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//输入参数
uniform sampler2D _NormalMap;
uniform sampler2D _MatCap;
uniform float _FresnelPow;
uniform float _EnvSpecInt;
//输入结构
struct VertexInput{
float4 vertex : POSITION;
float4 normal : NORMAL;
float4 tangent: TANGENT;
float2 uv0: TEXCOORD0; //将模型uv信息输入进0通道
};
//输出结构
struct VertexOutput{
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 posWS : TEXCOORD1;
float3 nDirWS : TEXCOORD2;
float3 tDirWS : TEXCOORD3;
float3 bDirWS : TEXCOORD4;
};
//输入结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v){
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4 (v.tangent.xyz,0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS) * v.tangent.w);
return o;
}
//输出结构>>>像素
float4 frag(VertexOutput i) : color{
//准备向量
float3 nDirTS =UnpackNormal(tex2D(_NormalMap, i.uv0)).rgb;
float3x3 TBN = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
float3 nDirWS = normalize(mul(nDirTS,TBN));
float3 nDirVS = mul(UNITY_MATRIX_V,nDirWS);
float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);
//中间变量
float vdotn = dot(vDirWS,nDirWS);//菲涅尔
float2 matcapUV = nDirVS.rg*0.5+0.5; //做uv用于采样Matcap
float3 matcap = tex2D(_MatCap, matcapUV);
float fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow);
float3 envSpecLighting = matcap*fresnel*_EnvSpecInt;
return float4(envSpecLighting,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
Cubemap是一个由六个独立的正方形纹理组成的集合,它将多个纹理组合起来映射到一个单一纹理。基本上说CubeMap包含6个2D纹理,这每个2D纹理是一个立方体(cube)的一个面,也就是说它是一个有贴图的立方体。
https://blog.csdn.net/v_xchen_v/article/details/79474193
代码:
Shader "Unlit/16_CubeMap"
{
Properties
{
_Cubemap ("环境球",Cube) = "_Skybox" {}
_NormalMap ("法线贴图", 2D) = "bump" {}
_CubemapMip ("环境球Mip", Range(0,7)) = 0
_FresnelPow ("菲涅尔次幂", Range(0,10)) = 1
_EnvSpecInt ("环境镜面反射强度", Range(0,5))=0.2
}
SubShader
{
Tags { "LightMode"="ForwardBase" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fog
#include "AutoLight.cginc" //投影头文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//输入参数
uniform samplerCUBE _Cubemap;
uniform sampler2D _NormalMap;
uniform float _CubemapMip;
uniform float _FresnelPow;
uniform float _EnvSpecInt;
//输入结构
struct VertexInput{
float4 vertex : POSITION;
float4 normal : NORMAL;
float4 tangent: TANGENT;
float2 uv0: TEXCOORD0; //将模型uv信息输入进0通道
};
//输出结构
struct VertexOutput{
float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float4 posWS : TEXCOORD1;
float3 nDirWS : TEXCOORD2;
float3 tDirWS : TEXCOORD3;
float3 bDirWS : TEXCOORD4;
};
//输入结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v){
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4 (v.tangent.xyz,0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS,o.tDirWS) * v.tangent.w);
return o;
}
//输出结构>>>像素
float4 frag(VertexOutput i) : color{
// 准备向量
float3 nDirTS = UnpackNormal(tex2D(_NormalMap, i.uv0)).rgb;
float3x3 TBN = float3x3(i.tDirWS, i.bDirWS, i.nDirWS);
float3 nDirWS = normalize(mul(nDirTS, TBN)); // 计算Fresnel 计算vrDirWS
float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz); // 计算Fresnel
float3 vrDirWS = reflect(-vDirWS, nDirWS);
// 准备中间变量
float vdotn = dot(vDirWS, nDirWS);
// 光照模型
float3 var_Cubemap = texCUBElod(_Cubemap, float4(vrDirWS, _CubemapMip)).rgb;// 采样Cubemap
float fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow);
float3 envSpecLighting = var_Cubemap * fresnel * _EnvSpecInt;
// 返回值
return float4(envSpecLighting, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
代码:
Shader "Unlit/17_OldSchoolPro"
{
Properties
{
[Header(Texture)]
_MainTex ("RGB:基础颜色 A:环境遮罩", 2D) = "white" {}
_NormTex ("RGB:法线贴图", 2D) = "bump" {}
_SpecTex ("RGB:高光颜色 A:高光次幂", 2D) = "gray" {}
_EmitTex ("RGB:自发光贴图", 2d) = "black" {}
_Cubemap ("RGB:环境贴图", cube) = "_Skybox" {}
[Header(Diffuse)]
_MainCol ("基本色", Color) = (0.5, 0.5, 0.5, 1.0)
_EnvDiffInt ("环境漫反射强度", Range(0, 1)) = 0.2
_EnvUpCol ("环境天顶颜色", Color) = (1.0, 1.0, 1.0, 1.0)
_EnvSideCol ("环境水平颜色", Color) = (0.5, 0.5, 0.5, 1.0)
_EnvDownCol ("环境地表颜色", Color) = (0.0, 0.0, 0.0, 0.0)
[Header(Specular)]
_SpecPow ("高光次幂", Range(1, 90)) = 30
_EnvSpecInt ("环境镜面反射强度", Range(0, 5)) = 0.2
_FresnelPow ("菲涅尔次幂", Range(0, 5)) = 1
_CubemapMip ("环境球Mip", Range(0, 7)) = 0
[Header(Emission)]
_EmitInt ("自发光强度", range(1, 10)) = 1
}
SubShader
{
Tags { "LightMode"="ForwardBase" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "AutoLight.cginc"//投影头文件
#include "Lighting.cginc"
#include "UnityCG.cginc"
//输入参数
// Texture
uniform sampler2D _MainTex;
uniform sampler2D _NormTex;
uniform sampler2D _SpecTex;
uniform sampler2D _EmitTex;
uniform samplerCUBE _Cubemap;
// Diffuse
uniform float3 _MainCol;
uniform float _EnvDiffInt;
uniform float3 _EnvUpCol;
uniform float3 _EnvSideCol;
uniform float3 _EnvDownCol;
// Specular
uniform float _SpecPow;
uniform float _FresnelPow;
uniform float _EnvSpecInt;
uniform float _CubemapMip;
// Emission
uniform float _EmitInt;
//输入结构
struct VertexInput{
float4 vertex : POSITION; // 顶点信息
float2 uv0 : TEXCOORD0; // UV信息
float4 normal : NORMAL; // 法线信息
float4 tangent : TANGENT; // 切线信息
};
//输出结构
struct VertexOutput{
float4 pos : SV_POSITION; // 屏幕顶点位置
float2 uv0 : TEXCOORD0; // UV0
float4 posWS : TEXCOORD1; // 世界空间顶点位置
float3 nDirWS : TEXCOORD2; // 世界空间法线方向
float3 tDirWS : TEXCOORD3; // 世界空间切线方向
float3 bDirWS : TEXCOORD4; // 世界空间副切线方向
LIGHTING_COORDS(5,6) // 投影相关
};
//输入结构>>>顶点shader>>>输出结构
VertexOutput vert (VertexInput v){
VertexOutput o = (VertexOutput)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.uv0 = v.uv0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); // 切线方向 OS>WS
o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w); // 副切线方向
TRANSFER_VERTEX_TO_FRAGMENT(o)//投影
return o;
}
//输出结构>>>像素
float4 frag(VertexOutput i) : color{
//准备向量
float3 nDirTS = UnpackNormal(tex2D(_NormTex, i.uv0)).rgb;
float3x3 TBN = float3x3(i.tDirWS,i.bDirWS,i.nDirWS);
float3 nDirWS = normalize(mul(nDirTS,TBN));
float3 vDirWS = normalize(_WorldSpaceCameraPos.xyz-i.posWS.xyz);
float3 vrDirWS = reflect(-vDirWS,nDirWS);
float3 lDirWS = _WorldSpaceLightPos0.xyz;
float3 lrDirWS = reflect(-lDirWS,nDirWS);
//准备中间向量
float ndotl = dot(nDirWS,lDirWS);
float vdotr = dot(vDirWS,lrDirWS);
float vdotn = dot(vDirWS,nDirWS);
//采样纹理
float4 var_MainTex = tex2D(_MainTex, i.uv0);
float4 var_SpecTex = tex2D(_SpecTex, i.uv0);
float3 var_EmitTex = tex2D(_EmitTex, i.uv0).rbg;
float3 var_Cubemap = texCUBElod(_Cubemap, float4(vrDirWS,lerp(_CubemapMip,0.0,var_SpecTex.a))).rgb;//youwenti
//光照模型(直接光照)
float3 baseCol = var_MainTex.rgb*_MainCol;
float lambert = max(0.0,ndotl);
float phong = pow(max(0.0,vdotr), _SpecPow);
float specCol = var_SpecTex.rgb;
float specPow = lerp(1,_SpecPow, var_SpecTex.a);//budong!!!
float shadow = LIGHT_ATTENUATION(i);
float3 dirLighting = (baseCol * lambert + specCol * phong)* _LightColor0 * shadow;
//光照模型(环境光照)
//计算各部分遮罩
float upMask = max(0.0, nDirWS.g);
float downMask = max(0.0, -nDirWS.g);
float sideMask = 1.0 - upMask - downMask;
//混合环境色
float3 envCol = _EnvUpCol*upMask +
_EnvSideCol*sideMask +
_EnvDownCol*downMask;
float fresnel = pow(max(0.0, 1.0 - vdotn), _FresnelPow);
float occlusion = var_MainTex.a;
//计算环境光照
float3 envLighting = (baseCol* envCol* _EnvDiffInt +
var_Cubemap * fresnel * _EnvSpecInt * var_SpecTex.a) * occlusion;
//自发光部分
float3 emission = var_EmitTex * _EmitInt;
//返回结果
float3 finaRGB = dirLighting + envLighting + emission;
return float4(finaRGB,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}