Code
//jave.lin 2019.06.17
//simple illumination
Shader "Custom/MyReflection"
{
Properties{
[NoScaleOffset] _MainTex("Main Tex", 2D) = "white" {}
[NoScaleOffset] _ReflectCube("Reflect Cube", Cube) = "white" {}
_ReflectIntensity("Reflection Intensity", Range(0,1)) = 0.5
_ReflectBrightness("Reflection Brightness", Range(1,2)) = 1
_SpecularIntensity("Specular Intensity", Range(0,1)) = 1
_AmbientIntensity("Ambient Intensity", Range(0,1)) = 1
_SelfShadowColor("Self Shadow Color", Color) = (0.5,0.5,0.5,0.5)
[Toggle] _HalfLambert("Half Lambert", Float) = 1
}
SubShader{
Pass{
Tags {"Queue" = "Opaque" "LightMode"="ForwardBase"} // shadow setup1:"LightMode"="ForwardBase"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase // shadow setup2:fwdbase
#include "UnityCG.cginc"
#include "Lighting.cginc" // shadow setup3:#include "Lighting.cginc"
#include "AutoLight.cginc" // shadow setup4:#include "AutoLight.cginc"
struct a2v{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed4 tc : TEXCOORD1;
LIGHTING_COORDS(2,3) // shadow setup5:LIGHTING_COORDS(n,n+1)
float3 worldNormal : TEXCOORD4;
float3 worldPos : TEXCOORD5;
float3 eyeDir : TEXCOORD6;
float3 lightDir : TEXCOORD7;
};
sampler2D _MainTex;
samplerCUBE _ReflectCube;
float _ReflectIntensity;
float _ReflectBrightness;
float _SpecularIntensity;
float _AmbientIntensity;
fixed4 _SelfShadowColor;
bool _HalfLambert;
v2f vert(a2v v){
v2f o = (v2f)0;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.eyeDir = normalize(_WorldSpaceCameraPos.xyz - o.worldPos).xyz;
o.lightDir = normalize(_WorldSpaceLightPos0.xyz);
TRANSFER_VERTEX_TO_FRAGMENT(o); // shadow setup6:TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
fixed4 frag(v2f i):SV_TARGET{
float3 normalDir = normalize(i.worldNormal);
float3 reflectDir = reflect(-i.eyeDir,normalDir);
fixed3 specularDir = reflect(-i.lightDir,normalDir);
fixed4 c = tex2D(_MainTex, i.uv); // albedo
fixed4 r = texCUBE(_ReflectCube, reflectDir); // enviroment cubemap
if(_HalfLambert){
c.xyz *= (dot(i.lightDir,normalDir) + 1) * 0.5; // diffuse
}else{
c.xyz *= dot(i.lightDir,normalDir); // diffuse
}
c.xyz += c.xyz * UNITY_LIGHTMODEL_AMBIENT.rgb; // ambient
float specularDotEye = max(0, dot(specularDir, i.eyeDir));
c.xyz += (_LightColor0.rgb) * specularDotEye * _SpecularIntensity; // specular
fixed3 skyDir = reflect(float3(0,-1,0),normalDir);
c.xyz += unity_AmbientSky.rgb * unity_AmbientSky.a * max(0, dot(skyDir, i.eyeDir)) * _AmbientIntensity; // ambient sky
fixed3 equatorDir = normalize(float3(_WorldSpaceCameraPos.x, i.worldPos.y, _WorldSpaceCameraPos.z) - i.worldPos).xyz;
equatorDir = reflect(-equatorDir,normalDir);
c.xyz += unity_AmbientEquator.rgb * unity_AmbientEquator.a * max(0, dot(equatorDir, i.eyeDir)) * _AmbientIntensity; // ambient equator
fixed3 groundDir = reflect(float3(0,1,0),normalDir);
c.xyz += unity_AmbientGround.rgb * unity_AmbientGround.a * max(0, dot(groundDir, i.eyeDir)) * _AmbientIntensity; // ambient ground
c.xyz = lerp(c.xyz,c.xyz*r.xyz*_ReflectBrightness,_ReflectIntensity); // reflection
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos); // shadow setup7:UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos)
atten = (atten + 1) * 0.5;
c.xyz *= atten; // lighting and shadow attenuation
return c;
}
ENDCG
}
}
Fallback "Diffuse"
}
Steps
在代码中查看setupN,了解说明查看下面的References链接
也可以参考我之后写的一篇:Unity Shader - Toon Shading - 卡通渲染 - 添加阴影 - 里头的注释写的很清楚:每一步的基本作用
- shadow setup1:“LightMode”=“ForwardBase”
- shadow setup2:fwdbase
- shadow setup3:#include “Lighting.cginc”
- shadow setup4:#include “AutoLight.cginc”
- shadow setup5:LIGHTING_COORDS(n,n+1)
- shadow setup6:TRANSFER_VERTEX_TO_FRAGMENT(o)
- shadow setup7:UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos)
另外参考
Adding Shadows to a Unity Vertex/Fragment Shader in 7 Easy Steps
Shader "Custom/SolidColor" {
SubShader {
Pass {
// 1.) This will be the base forward rendering pass in which ambient, vertex, and
// main directional light will be applied. Additional lights will need additional passes
// using the "ForwardAdd" lightmode.
// see: http://docs.unity3d.com/Manual/SL-PassTags.html
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 2.) This matches the "forward base" of the LightMode tag to ensure the shader compiles
// properly for the forward bass pass. As with the LightMode tag, for any additional lights
// this would be changed from _fwdbase to _fwdadd.
#pragma multi_compile_fwdbase
// 3.) Reference the Unity library that includes all the lighting shadow macros
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
// 4.) The LIGHTING_COORDS macro (defined in AutoLight.cginc) defines the parameters needed to sample
// the shadow map. The (0,1) specifies which unused TEXCOORD semantics to hold the sampled values -
// As I'm not using any texcoords in this shader, I can use TEXCOORD0 and TEXCOORD1 for the shadow
// sampling. If I was already using TEXCOORD for UV coordinates, say, I could specify
// LIGHTING_COORDS(1,2) instead to use TEXCOORD1 and TEXCOORD2.
LIGHTING_COORDS(0,1)
};
v2f vert(appdata_base v) {
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
// 5.) The TRANSFER_VERTEX_TO_FRAGMENT macro populates the chosen LIGHTING_COORDS in the v2f structure
// with appropriate values to sample from the shadow/lighting map
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
fixed4 frag(v2f i) : COLOR {
// 6.) The LIGHT_ATTENUATION samples the shadowmap (using the coordinates calculated by TRANSFER_VERTEX_TO_FRAGMENT
// and stored in the structure defined by LIGHTING_COORDS), and returns the value as a float.
float attenuation = LIGHT_ATTENUATION(i);
return fixed4(1.0,0.0,0.0,1.0) * attenuation;
}
ENDCG
}
}
// 7.) To receive or cast a shadow, shaders must implement the appropriate "Shadow Collector" or "Shadow Caster" pass.
// Although we haven't explicitly done so in this shader, if these passes are missing they will be read from a fallback
// shader instead, so specify one here to import the collector/caster passes used in that fallback.
Fallback "VertexLit"
Runtime
Project
SurfaceShaderTest_SampleScene_测试环境反射 提取码: 3sng
unity version : 2019.1.7f1 运行SampleScene