WikiBooks/Cg Programming

https://en.wikibooks.org/wiki/Cg_Programming

Basics

Minimal Shader(about shaders, materials, and game objects)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg basic shader" {    //defines the name of the shader    
 4     SubShader {    //unity chooses the subshader that fits the GPU best
 5         Pass {    //some shaders require multiple passes
 6             CGPROGRAM //here begins the part in Unity's Cg
 7 
 8             #pragma vertex vert    //this specifies the vert function as the vertex shader
 9             #pragma fragment frag    //this specifies the frag function as the fragment shader
10 
11             float4 vert(float4 vertexPos:POSITION) : SV_POSITION {    //vertex shader
12                 //this line transforms the vertex input parameter
13                 //vertexPos with the built-in matrix UNITY_MATRIX_MVP
14                 //and return it as a nameless vertex output parameter                
15                 return UnityObjectToClipPos(vertexPos);    //mul(UNITY_MATRIX_MVP,vertexPos)
16             }
17 
18             float4 frag():COLOR    { //fragment shader
19                 //this fragment shader returns a nameless fragment
20                 //output parameter (with semantic COLOR) that is set to
21                 //opaque red(red = 1,green = 0,blue = 0, alpha = 1)
22                 return float4(1.0,0.0,0.0,1.0);
23             }
24 
25             ENDCG    //here ends the part in Cg
26         }
27     }
28 }
Basic Shader

RGB Cube(about vertex output parameters)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader for RGB Cube"{
 4     SubShader{
 5         Pass{
 6             CGPROGRAM
 7 
 8             #pragma vertex vert    //vert function is the vertex shader
 9             #pragma fragment frag    //frag function is the fragment shader
10 
11             //for multiple vertex output parameters an ouput structure is defined
12             struct vertexOutput{
13                 float4 pos:SV_POSITION;
14                 float4 col:TEXCOORD0;
15                 //nointerpolation float4 col:TEXCOORD0;
16             };
17 
18             //vertext shader
19             vertexOutput vert(float4 vertexPos:POSITION){
20                 vertexOutput output;    //we don't need to type 'struct' here
21 
22                 output.pos = UnityObjectToClipPos(vertexPos);
23                 output.col = vertexPos+float4(0.5,0.5,0.5,0.0);
24 
25                 //here the vertex shader writes output data to the output structure.
26                 //we add 0.5 to the x,y,z coordinates,because the coordinates of the cube are between -0.5 and 0.5
27                 //but we need them between 0.0 and 1.0
28                 return output;
29             }
30 
31             //fragment shader
32             float4 frag(vertexOutput input):COLOR {
33                 //here the fragment shader returns the "col" input parameter with semantic TEXCOORD0 as nameless
34                 //output parameter with semantic COLOR
35                 return input.col;
36             }
37 
38             ENDCG
39         }
40     }
41 }
Shader for RGB Cube
 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader for RGB Cube"{
 4     SubShader{
 5         Pass{
 6             CGPROGRAM
 7 
 8             #pragma vertex vert    //vert function is the vertex shader
 9             #pragma fragment frag    //frag function is the fragment shader
10 
11             void vert(float4 vertexPos:POSITION,out float4 pos:SV_POSITION,out float4 col:TEXCOORD0){
12                 pos = UnityObjectToClipPos(vertexPos);
13                 col = vertexPos+float4(0.5,0.5,0.5,0.0);
14                 return;
15             }
16 
17             float4 frag(float4 pos:SV_POSITION,float4 col:TEXCOORD0):COLOR{
18                 return col;
19             }
20 
21             ENDCG
22         }
23     }
24 }
Shader for RGB Cube

Debugging of shaders(about vertex input parameters)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader with all built-in vertex input parameters" {
 4     SubShader {
 5         Pass{
 6             CGPROGRAM
 7 
 8             #pragma vertex vert
 9             #pragma fragment frag
10 
11             struct vertexInput{
12                 float4 vertex:POSITION;        //position(in object coordinates,i.e. local or model coordinates)
13                 float4 tangent:TANGENT;        //vector orthogonal to the surface normal
14                 float3 normal:NORMAL;        //surface normal vector(in object coordinates;usually normalized to unit length)
15                 float4 texcoord:TEXCOORD0;    //0th set of texture,coordinates(a.k.a "UV";between 0 and 1)
16                 float4 texcoord1:TEXCOORD1;    //1st set of tex.coors.
17                 float4 texcoord2:TEXCOORD2;    //2nd set of tex.coors.
18                 float4 texcoord3:TEXCOORD3;    //3rd set of tex.coors.
19                 fixed4 color:COLOR;            //color(usually constant)
20             };
21 
22             struct vertexOutput{
23                 float4 pos:SV_POSITION;
24                 float4 col:TEXCOOORD0;
25             };
26 
27             vertexOutput vert(vertexInput input){
28                 vertexOutput output;
29                 output.pos = UnityObjectToClipPos(input.vertex);
30                 //output.col = input.texcoord;    //set the output color
31 
32                 //other possibilities to play with:
33 
34                 //output.col = input.vertex;
35                 //output.col = input.tangent;
36                 //output.col = float4(input.normal,1.0);
37                 //output.col = input.texcoord;
38                 //output.col = input.texcoord1;
39                 //output.col = input.texcoord2;
40                 //output.col = input.texcoord3;
41                 output.col = input.color;
42 
43                 return output;
44             }
45 
46             float4 frag(vertexOutput input):COLOR{
47                 return input.col;
48             }
49 
50             ENDCG
51         }
52     }
53 }
Shader with all built-in vertex input parameters
 1 //struct appdata_base {
 2 //    float4 vertex : POSITION;
 3 //    float3 normal : NORMAL;
 4 //    float4 texcoord : TEXCOORD0;
 5 //};
 6 //struct appdata_tan {
 7 //    float4 vertex : POSITION;
 8 //    float4 tangent : TANGENT;
 9 //    float3 normal : NORMAL;
10 //    float4 texcoord : TEXCOORD0;
11 //};
12 //struct appdata_full {
13 //    float4 vertex : POSITION;
14 //    float4 tangent : TANGENT;
15 //    float3 normal : NORMAL;
16 //    float4 texcoord : TEXCOORD0;
17 //    float4 texcoord1 : TEXCOORD1;
18 //    float4 texcoord2 : TEXCOORD2;
19 //    float4 texcoord3 : TEXCOORD3;
20 //    fixed4 color : COLOR;
21 //    // and additional texture coordinates only on XBOX360
22 //};
23 //struct appdata_img {
24 //    float4 vertex : POSITION;
25 //    half2 texcoord : TEXCOORD0;
26 //};
27 
28 Shader "Custom/Cg shader with all built-in vertex input parameters" {
29     SubShader {
30         Pass{
31             CGPROGRAM
32 
33             #pragma vertex vert
34             #pragma fragment frag
35             #include "UnityCG.cginc"
36 
37             struct vertexOutput{
38                 float4 pos:SV_POSITION;
39                 float4 col:TEXCOOORD0;
40             };
41 
42             vertexOutput vert(appdata_full input){
43                 vertexOutput output;
44 
45                 output.pos = UnityObjectToClipPos(input.vertex);
46                 output.col = input.texcoord;
47 
48                 return output;
49             }
50 
51             float4 frag(vertexOutput input):COLOR{
52                 return input.col;
53             }
54 
55             ENDCG
56         }
57     }
58 }
Shader with all built-in vertex input parameters

Shading in World Space(about uniforms)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 3 
 4 Shader "Custom/Cg shading in world space" {
 5     SubShader{
 6         Pass{
 7             CGPROGRAM
 8 
 9             #pragma vertex vert
10             #pragma fragment frag
11 
12             //uniform float4x4 _Object2World;
13             //automatic definition of a Unity-specific uniform parameter
14             struct vertexInput{
15                 float4 vertex:POSITION;
16             };
17 
18             struct vertexOutput{
19                 float4 pos:SV_POSITION;
20                 float4 position_in_world_space:TEXCOORD0;
21             };
22 
23             vertexOutput vert(vertexInput input){
24                 vertexOutput output;
25 
26                 output.pos = UnityObjectToClipPos(input.vertex);
27                 //transformation of input.vertex from object coordinates to world coordinates;
28                 output.position_in_world_space = mul(unity_ObjectToWorld,input.vertex);
29 
30                 return output;
31             }
32 
33             float4 frag(vertexOutput input):COLOR{
34                 //computes the distance between the fragment position and the origin(the 4th coordinates should always be 1 for points)
35                 float dist = distance(input.position_in_world_space,float4(0.0,0.0,0.0,1.0));
36 
37                 if(dist < 1){
38                     return float4(0.0,1.0,0.0,1.0);
39                 } else {
40                     return float4(0.1,0.1,0.1,1.0);
41                 }
42             }
43 
44             ENDCG
45         }
46     }
47 }
Shading in World Space
 1 uniform float4 _Time,_SinTime,_CosTime;    //time values
 2 uniform float4 _ProjectionParams;    //x = 1 or -1 (-1 if projection is flipped) y = near plane; z = far plane; w = 1/far plane
 3 uniform float4 _ScreenParams;    //x = width;y = height; z = 1 + 1/width; w = 1+1/height
 4 uniform float3 _WorldSpaceCameraPos;
 5 uniform float4x4 _Object2World;    //model(local)matrix
 6 uniform float4x4 _World2Object;    //inverse model matrix
 7 uniform float4 _WorldSpaceLightPos();    //position or direction of light source for forward rendering
 8 uniform float4x4 UNITY_MATRIX_MVP;    //model view projection matrix
 9 uniform float4x4 UNITY_MATRIX_MV;    //model view matrix
10 uniform float4x4 UNITY_MATRIX_V;    //view matrix
11 uniform float4x4 UNITY_MATRIX_P;    //projection matrix
12 uniform float4x4 UNITY_MATRIX_VP;    //view projection matrix
13 uniform float4x4 UNITY_MATRIX_T_MV;    //transpose of model view matrix
14 uniform float4x4 UNITY_MATRIX_IT_MV;//transpose of the inverse model view matrix
15 uniform float4 UNITY_LIGHTMODEL_AMBIENT;    //ambient color
More Unity-Specific Uniforms

Transparent Surfaces

Cutaways(about discarding fragments and triangle-face culling)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader using discard" {
 4     SubShader{
 5         Pass{
 6             //turn off triangle culling,alternatives are:
 7             //Cull Back(or nothing):cull only back faces
 8             //Cull Front:cull only front faces
 9             Cull off    
10 
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             struct vertexInput{
17                 float4 vertex:POSITION;
18             };
19 
20             struct vertexOutput{
21                 float4 pos:SV_POSITION;
22                 float4 posInObjectCoords:TEXCOORD0;
23             };
24 
25             vertexOutput vert(vertexInput input){
26                 vertexOutput output;
27                 
28                 output.pos = UnityObjectToClipPos(input.vertex);
29                 output.posInObjectCoords = input.vertex;
30 
31                 return output;
32             }
33 
34             float4 frag(vertexOutput input):COLOR{
35                 if(input.posInObjectCoords.y > 0.0){
36                     //return float4(1.0,0.0,0.0,1.0);
37                     discard;    //drop the fragment if y coordinate > 0
38                 }
39                 return float4(0.0,1.0,0.0,1.0);    //green
40             }
41 
42             ENDCG
43         }
44     }
45 }
Shader using discard

 

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 3 
 4 Shader "Custom/Cg shader with two passes using discard" {
 5     SubShader{
 6         // first pass (is executed before the second pass)
 7         Pass{
 8             Cull Front    // cull only front faces
 9 
10             CGPROGRAM
11 
12             #pragma vertex vert
13             #pragma fragment frag
14 
15             struct vertexInput{
16                 float4 vertex:POSITION;
17             };
18 
19             struct vertexOutput{
20                 float4 pos:SV_POSITION;
21                 float4 posInObjectCoords:TEXCOORD0;
22             };
23 
24             vertexOutput vert(vertexInput input){
25                 vertexOutput output;
26 
27                 output.pos = UnityObjectToClipPos(input.vertex);
28                 output.posInObjectCoords = input.vertex;
29                 
30                 return output;
31             }
32 
33             float4 frag(vertexOutput input):COLOR{
34                 if(input.posInObjectCoords.y > 0.0){
35                     discard;// drop the fragment  if y coordinate > 0
36                 }
37                 return float4(1.0,0.0,0.0,1.0);    // red
38             }
39 
40             ENDCG
41         }
42         // second pass (is executed after the first pass)
43         Pass{
44             Cull Back // cull only back faces
45 
46             CGPROGRAM
47 
48             #pragma vertex vert
49             #pragma fragment frag
50 
51             struct vertexInput{
52                 float4 vertex:POSITION;
53             };
54 
55             struct vertexOutput{
56                 float4 pos:SV_POSITION;
57                 float4 posInObjectCoords:TEXCOORD0;
58             };
59 
60             vertexOutput vert(vertexInput input){
61                 vertexOutput output;
62 
63                 output.pos = UnityObjectToClipPos(input.vertex);
64                 output.posInObjectCoords = input.vertex;
65 
66                 return output;
67             }
68 
69             float4 frag(vertexOutput input):COLOR{
70                 if(input.posInObjectCoords.y > 0.0){
71                     discard; // drop the fragment if y coordinate > 0
72                 }
73                 return float4(0.0,1.0,0.0,1.0);    // green
74             }
75 
76             ENDCG
77         }
78     }
79 }
Shader with two passes using discard

Transparency(about blending)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader using blending" {
 4     SubShader{
 5         Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
 6         Pass{
 7             ZWrite Off // don't write to depth buffer in order not to occlude other objects
 8 
 9             Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
10 
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             float4 vert(float4 vertexInput:POSITION):SV_POSITION{
17                 
18                 return UnityObjectToClipPos(vertexInput);
19             }
20 
21             float4 frag():COLOR{
22                 // the fourth components(alpha) is important: this is semitransparent green
23                 return float4(0.0,1.0,0.0,0.3);
24             }
25 
26             ENDCG
27         }
28     }
29 }
Shader using blending

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 3 
 4 Shader "Cg shader using blending" {
 5     Subshader{
 6         // draw after all opaque geometry has been drawn
 7         Tags { "Queue" = "Transparent" }
 8         Pass {        
 9             Cull Front // first pass renders only back faces (the "inside")
10             ZWrite Off // don't write to depth buffer in order not to occlude other objects
11             Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
12 
13             CGPROGRAM
14 
15             #pragma vertex vert
16             #pragma fragment frag
17 
18             float4 vert(float4 vertexPos:POSITION):SV_POSITION{
19                 return UnityObjectToClipPos(vertexPos);
20             }
21 
22             float4 frag():COLOR{
23                 // the fourth component(alpha) is important:this is semitransparent red
24                 return float4(1.0,0.0,0.0,0.3);
25             }
26 
27             ENDCG
28         }
29 
30         Pass {
31             Cull Back // second pass renders only front faces (the "outside")
32             ZWrite Off // don't write to depth buffer in order not to occlude other objects
33             Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
34 
35             CGPROGRAM
36 
37             #pragma vertex vert
38             #pragma fragment frag
39 
40             float4 vert(float4 vertexPos:POSITION):SV_POSITION{
41                 return UnityObjectToClipPos(vertexPos);
42             }
43 
44             float4 frag():COLOR{
45                 // the fourth component(alpha) is important:this is semitransparent green;
46                 return float4(0.0,1.0,0.0,0.3);
47             }
48 
49             ENDCG
50         }
51     }
52 }
Shader using blending

Order-Independent Transparency(about order-independent blending)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader using additive blending" {
 4     SubShader{
 5         Tags { "Queue" = "Transparent" }    // draw after all opaque geometry has been drawn
 6         Pass{
 7             Cull Off // draw front and back faces
 8             ZWrite Off // don't write to depth buffer in order not to occlude other objects
 9             Blend SrcAlpha One // additive blending
10 
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             float4 vert(float4 vertexPos:POSITION):SV_POSITION{
17                 return UnityObjectToClipPos(vertexPos);
18             }
19             
20             float4 frag():COLOR{
21                 return float4(1.0,0.0,0.0,0.2);
22             }
23 
24             ENDCG
25         }
26     }
27 }
Shader using additive blending

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader using multiplicative blending" {
 4    SubShader {
 5       Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
 6       Pass { 
 7          Cull Off // draw front and back faces
 8          ZWrite Off // don't write to depth buffer in order not to occlude other objects
 9          Blend Zero OneMinusSrcAlpha // multiplicative blending for attenuation by the fragment's alpha
10 
11          CGPROGRAM 
12  
13          #pragma vertex vert 
14          #pragma fragment frag
15  
16          float4 vert(float4 vertexPos : POSITION) : SV_POSITION 
17          {
18             return UnityObjectToClipPos(vertexPos);
19          }
20  
21          float4 frag(void) : COLOR 
22          {
23             return float4(1.0, 0.0, 0.0, 0.2); 
24          }
25  
26          ENDCG  
27       }
28    }
29 }
Shader using multiplicative blending

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg Shader using order-independent blending" {
 4     SubShader{
 5         Tags { "Queue" = "Transparent" }    // draw after all opaque geometry has been drawn
 6         Pass{
 7             Cull Off // draw front and back faces
 8             ZWrite Off // don't write to depth buffer in order not to occlude other objects
 9             Blend Zero OneMinusSrcAlpha // multiplicative blending for attenuation by fragment's alpha
10 
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             float4 vert(float4 vertexPos:POSITION):SV_POSITION{
17                 return UnityObjectToClipPos(vertexPos);
18             }
19 
20             float4 frag():COLOR{
21                 return float4(1.0,0.0,0.0,0.2);
22             }
23 
24             ENDCG
25         }
26 
27         Pass{
28             Cull Off // draw front and back faces
29             ZWrite Off // don't write to depth buffer in order not to occlude other objects
30             Blend SrcAlpha One // additive blending to add colors
31 
32             CGPROGRAM
33 
34             #pragma vertex vert
35             #pragma fragment frag
36 
37             float4 vert(float4 vertexPos:POSITION):SV_POSITION{
38                 return UnityObjectToClipPos(vertexPos);
39             }
40 
41             float4 frag():COLOR{
42                 return float4(1.0,0.0,0.0,0.2);
43             }
44 
45             ENDCG
46         }
47     }
48 }
Shader using order-independent blending

Silhouette Enhancement(about transforming normal vectors)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg silhouette enhancement" {
 6    Properties {
 7       _Color ("Color", Color) = (1, 1, 1, 0.5) // user-specified RGBA color including opacity         
 8    }
 9    SubShader {
10       Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn         
11       Pass { 
12          ZWrite Off // don't occlude other objects
13          Blend SrcAlpha OneMinusSrcAlpha // standard alpha blending
14  
15          CGPROGRAM 
16  
17          #pragma vertex vert  
18          #pragma fragment frag 
19  
20          #include "UnityCG.cginc"
21  
22          uniform float4 _Color; // define shader property for shaders
23  
24          struct vertexInput {
25             float4 vertex : POSITION;
26             float3 normal : NORMAL;
27          };
28          struct vertexOutput {
29             float4 pos : SV_POSITION;
30             float3 normal : TEXCOORD;
31             float3 viewDir : TEXCOORD1;
32          };
33  
34          vertexOutput vert(vertexInput input) 
35          {
36             vertexOutput output;
37  
38             float4x4 modelMatrix = unity_ObjectToWorld;
39             float4x4 modelMatrixInverse = unity_WorldToObject; 
40  
41             output.normal = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
42             output.viewDir = normalize(_WorldSpaceCameraPos - mul(modelMatrix, input.vertex).xyz);
43  
44             output.pos = UnityObjectToClipPos(input.vertex);
45             return output;
46          }
47  
48          float4 frag(vertexOutput input) : COLOR
49          {
50             float3 normalDirection = normalize(input.normal);
51             float3 viewDirection = normalize(input.viewDir);
52  
53             float newOpacity = min(1.0, _Color.a / abs(dot(viewDirection, normalDirection)));
54             return float4(_Color.rgb, newOpacity);
55          }
56  
57          ENDCG
58       }
59    }
60 }
Silhouette Enhancement

Basic Lighting

Diffuse Reflection(about per-vertex diffuse lighting and multiple light sources of different kinds)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg per-vertex diffuse lighting" {
 6     Properties {
 7         _Color ("Diffuse Material Color",Color) = (1,1,1,1)
 8     }
 9 
10     SubShader{
11         Pass{
12             Tags { "LightMode" = "ForwardBase" }    // make sure that all uniforms are correctly set
13 
14             CGPROGRAM
15 
16             #pragma vertex vert
17             #pragma fragment frag
18 
19             #include "UnityCG.cginc"
20 
21             uniform float4 _LightColor0;    // color of light source(from "Lighting.cginc")
22             uniform float4 _Color;    // define shader property for shaders
23 
24             struct vertexInput{
25                 float4 vertex:POSITION;
26                 float3 normal:NORMAL;
27             };
28 
29             struct vertexOutput{
30                 float4 pos:SV_POSITION;
31                 float4 col:COLOR;
32             };
33 
34             vertexOutput vert(vertexInput input){
35                 vertexOutput output;
36 
37                 float4x4 modelMatrix = unity_ObjectToWorld;
38                 float4x4 modelMatrixInverse = unity_WorldToObject;
39 
40                 float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
41                 float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
42 
43                 float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
44 
45                 output.col = float4(diffuseReflection,1.0);
46                 output.pos = UnityObjectToClipPos(input.vertex);
47                 return output;
48             }
49 
50             float4 frag(vertexOutput input):COLOR{
51                 return input.col;
52             }
53 
54             ENDCG
55         }
56     }
57 
58     Fallback "Diffuse"
59 }
Per-vertex diffuse lighting
  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Cg per-vertex diffuse lighting" {
  6     Properties {
  7         _Color ("Diffuse Material Color",Color) = (1,1,1,1)
  8     }
  9     SubShader {
 10         //Pass for first light source
 11         Pass{
 12             Tags { "LightMode" = "ForwardBase" }
 13 
 14             CGPROGRAM
 15 
 16             #pragma vertex vert
 17             #pragma fragment frag
 18 
 19             #include "UnityCG.cginc"
 20             
 21             uniform float4 _LightColor0; //color of light source (from "Lighting.cginc")
 22             uniform float4 _Color; //define shader property for shader
 23 
 24             struct vertexInput{
 25                 float4 vertex:POSITION;
 26                 float3 normal:NORMAL;
 27             };
 28 
 29             struct vertexOutput{
 30                 float4 pos:SV_POSITION;
 31                 float4 col:COLOR;
 32             };
 33 
 34             vertexOutput vert(vertexInput input){
 35                 vertexOutput output;
 36 
 37                 float4x4 modelMatrix = unity_ObjectToWorld;
 38                 float4x4 modelMatrixInverse = unity_WorldToObject;
 39 
 40                 float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
 41                 float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 42 
 43                 float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
 44 
 45                 output.col = float4(diffuseReflection,1.0);
 46                 output.pos = UnityObjectToClipPos(input.vertex);
 47 
 48                 return output;
 49             }
 50 
 51             float4 frag(vertexOutput input):COLOR{
 52                 return input.col;
 53             }
 54 
 55             ENDCG
 56         }
 57 
 58         Pass {
 59             // pass for additional light source
 60             Tags { "LightMode" = "ForwardAdd" }
 61 
 62             // additional blending
 63             Blend One One
 64 
 65             CGPROGRAM
 66 
 67             #pragma vertex vert
 68             #pragma fragment frag
 69 
 70             #include "UnityCG.cginc"
 71 
 72             // color of light source (from "Lighting.cginc")
 73             uniform float4 _LightColor0;
 74             // define shader property for shaders
 75             uniform float4 _Color;
 76 
 77             struct vertexInput{
 78                 float4 vertex:POSITION;
 79                 float3 normal:NORMAL;
 80             };
 81 
 82             struct vertexOutput{
 83                 float4 pos:SV_POSITION;
 84                 float4 col:COLOR;
 85             };
 86 
 87             vertexOutput vert(vertexInput input){
 88                 vertexOutput output;
 89 
 90                 float4x4 modelMatrix = unity_ObjectToWorld;
 91                 float4x4 modelMatrixInverse = unity_WorldToObject;
 92 
 93                 float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
 94                 float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 95 
 96                 float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
 97 
 98                 output.col = float4(diffuseReflection,1.0);
 99                 output.pos = UnityObjectToClipPos(input.vertex);
100                 return output;
101             }
102 
103             float4 frag(vertexOutput input):COLOR{
104                 return input.col;
105             }
106 
107             ENDCG
108         }
109     }
110 
111     Fallback "Diffuse"
112 }
Per-vertex diffuse lighting
  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg per-vertex diffuse lighting" {
  6     Properties {
  7         _Color ("Diffuse Material Color",Color) = (1,1,1,1)
  8     }
  9     SubShader{
 10         Pass{
 11             // pass for first light source
 12             Tags { "LightMode" = "ForwardBase" }
 13 
 14             CGPROGRAM
 15 
 16             #pragma vertex vert
 17             #pragma fragment frag
 18 
 19             #include "UnityCG.cginc"
 20 
 21             // color of light source(from "Lighting.cginc")
 22             uniform float4 _LightColor0;
 23             // define shader property for shaders
 24             uniform float4 _Color;
 25 
 26             struct vertexInput{
 27                 float4 vertex:POSITION;
 28                 float3 normal:NORMAL;
 29             };
 30             struct vertexOutput{
 31                 float4 pos:SV_POSITION;
 32                 float4 col:COLOR;
 33             };
 34 
 35             vertexOutput vert(vertexInput input){
 36                 vertexOutput output;
 37 
 38                 float4x4 modelMatrix = unity_ObjectToWorld;
 39                 float4x4 modelMatrixInverse = unity_WorldToObject;
 40 
 41                 float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
 42                 float3 lightDirection;
 43                 float attenuation;
 44 
 45                 if(_WorldSpaceLightPos0.w == 0.0){ // directional light
 46                     attenuation = 1.0;    // no attenuation
 47                     lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 48                 } else {    // point or spot light
 49                     float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - mul(modelMatrix,input.vertex).xyz;
 50                     float distance = length(vertexToLightSource);
 51                     attenuation = 1.0 / distance;    // linear attenuation
 52                     lightDirection = normalize(vertexToLightSource);
 53                 }
 54 
 55                 float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
 56 
 57                 output.col = float4(diffuseReflection,1.0);
 58                 output.pos = UnityObjectToClipPos(input.vertex);
 59                 return output;
 60             }
 61 
 62             float4 frag(vertexOutput input):COLOR{
 63                 return input.col;
 64             }
 65 
 66             ENDCG
 67         }
 68 
 69         Pass {
 70             // pass for addtional light source
 71             Tags { "LightMode" = "ForwardAdd" }
 72 
 73             Blend One One // additive blending
 74 
 75             CGPROGRAM
 76 
 77             #pragma vertex vert
 78             #pragma fragment frag
 79 
 80             #include "UnityCG.cginc"
 81 
 82             // color of light source(from "Lighting.cginc")
 83             uniform float4 _LightColor0;
 84             // define shader property for shaders
 85             uniform float4 _Color;
 86 
 87             struct vertexInput{
 88                 float4 vertex:POSITION;
 89                 float3 normal:NORMAL;
 90             };
 91             struct vertexOutput{
 92                 float4 pos:SV_POSITION;
 93                 float4 col:COLOR;
 94             };
 95 
 96             vertexOutput vert(vertexInput input){
 97                 vertexOutput output;
 98 
 99                 float4x4 modelMatrix = unity_ObjectToWorld;
100                 float4x4 modelMatrixInverse = unity_WorldToObject;
101 
102                 float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
103                 float3 lightDirection;
104                 float attenuation;
105 
106                 if(_WorldSpaceLightPos0.w == 0.0){    // directional light
107                     attenuation = 1.0;    // no attenuation
108                     lightDirection = normalize(_WorldSpaceLightPos0.xyz);
109                 } else {    // point or spot light
110                     float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - mul(modelMatrix,input.vertex).xyz;
111                     float distance = length(vertexToLightSource);
112                     attenuation = 1.0 / distance;// linear attenuation
113                     lightDirection = normalize(vertexToLightSource);
114                 }
115 
116                 float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
117 
118                 output.col = float4(diffuseReflection,1.0);
119                 output.pos = UnityObjectToClipPos(input.vertex);
120                 
121                 return output;
122             }
123 
124             float4 frag(vertexOutput input):COLOR{
125                 return input.col;
126             }
127 
128             ENDCG
129         }
130     }
131 
132     Fallback "Diffuse"
133 }
Per-vertex diffuse lighting

Specular Highlights(about per-vertex lighting)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg per-vertex lighting" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _Shininess ("Shininess", Float) = 10
 10    }
 11    SubShader {
 12       Pass {    
 13          Tags { "LightMode" = "ForwardBase" } 
 14             // pass for ambient light and first light source
 15  
 16          CGPROGRAM
 17  
 18          #pragma vertex vert  
 19          #pragma fragment frag 
 20  
 21          #include "UnityCG.cginc"
 22          uniform float4 _LightColor0; 
 23             // color of light source (from "Lighting.cginc")
 24  
 25          // User-specified properties
 26          uniform float4 _Color; 
 27          uniform float4 _SpecColor; 
 28          uniform float _Shininess;
 29  
 30          struct vertexInput {
 31             float4 vertex : POSITION;
 32             float3 normal : NORMAL;
 33          };
 34          struct vertexOutput {
 35             float4 pos : SV_POSITION;
 36             float4 col : COLOR;
 37          };
 38  
 39          vertexOutput vert(vertexInput input) 
 40          {
 41             vertexOutput output;
 42  
 43             float4x4 modelMatrix = unity_ObjectToWorld;
 44             float3x3 modelMatrixInverse = unity_WorldToObject;
 45             float3 normalDirection = normalize(
 46                mul(input.normal, modelMatrixInverse));
 47             float3 viewDirection = normalize(_WorldSpaceCameraPos 
 48                - mul(modelMatrix, input.vertex).xyz);
 49             float3 lightDirection;
 50             float attenuation;
 51  
 52             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 53             {
 54                attenuation = 1.0; // no attenuation
 55                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 56             } 
 57             else // point or spot light
 58             {
 59                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
 60                   - mul(modelMatrix, input.vertex).xyz;
 61                float distance = length(vertexToLightSource);
 62                attenuation = 1.0 / distance; // linear attenuation 
 63                lightDirection = normalize(vertexToLightSource);
 64             }
 65  
 66             float3 ambientLighting = 
 67                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 68  
 69             float3 diffuseReflection = 
 70                attenuation * _LightColor0.rgb * _Color.rgb
 71                * max(0.0, dot(normalDirection, lightDirection));
 72  
 73             float3 specularReflection;
 74             if (dot(normalDirection, lightDirection) < 0.0) 
 75                // light source on the wrong side?
 76             {
 77                specularReflection = float3(0.0, 0.0, 0.0); 
 78                   // no specular reflection
 79             }
 80             else // light source on the right side
 81             {
 82                specularReflection = attenuation * _LightColor0.rgb 
 83                   * _SpecColor.rgb * pow(max(0.0, dot(
 84                   reflect(-lightDirection, normalDirection), 
 85                   viewDirection)), _Shininess);
 86             }
 87  
 88             output.col = float4(ambientLighting + diffuseReflection 
 89                + specularReflection, 1.0);
 90             output.pos = UnityObjectToClipPos(input.vertex);
 91             return output;
 92          }
 93  
 94          float4 frag(vertexOutput input) : COLOR
 95          {
 96             return input.col;
 97          }
 98  
 99          ENDCG
100       }
101  
102       Pass {    
103          Tags { "LightMode" = "ForwardAdd" } 
104             // pass for additional light sources
105          Blend One One // additive blending 
106  
107          CGPROGRAM
108  
109          #pragma vertex vert  
110          #pragma fragment frag 
111  
112          #include "UnityCG.cginc"
113          uniform float4 _LightColor0; 
114             // color of light source (from "Lighting.cginc")
115  
116          // User-specified properties
117          uniform float4 _Color; 
118          uniform float4 _SpecColor; 
119          uniform float _Shininess;
120  
121          struct vertexInput {
122             float4 vertex : POSITION;
123             float3 normal : NORMAL;
124          };
125          struct vertexOutput {
126             float4 pos : SV_POSITION;
127             float4 col : COLOR;
128          };
129  
130          vertexOutput vert(vertexInput input) 
131          {
132             vertexOutput output;
133  
134             float4x4 modelMatrix = unity_ObjectToWorld;
135             float3x3 modelMatrixInverse = unity_WorldToObject;
136             float3 normalDirection = normalize(
137                mul(input.normal, modelMatrixInverse));
138             float3 viewDirection = normalize(_WorldSpaceCameraPos 
139                - mul(modelMatrix, input.vertex).xyz);
140             float3 lightDirection;
141             float attenuation;
142  
143             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
144             {
145                attenuation = 1.0; // no attenuation
146                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
147             } 
148             else // point or spot light
149             {
150                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
151                   - mul(modelMatrix, input.vertex).xyz;
152                float distance = length(vertexToLightSource);
153                attenuation = 1.0 / distance; // linear attenuation 
154                lightDirection = normalize(vertexToLightSource);
155             }
156  
157             float3 diffuseReflection = 
158                attenuation * _LightColor0.rgb * _Color.rgb
159                * max(0.0, dot(normalDirection, lightDirection));
160  
161             float3 specularReflection;
162             if (dot(normalDirection, lightDirection) < 0.0) 
163                // light source on the wrong side?
164             {
165                specularReflection = float3(0.0, 0.0, 0.0); 
166                   // no specular reflection
167             }
168             else // light source on the right side
169             {
170                specularReflection = attenuation * _LightColor0.rgb 
171                   * _SpecColor.rgb * pow(max(0.0, dot(
172                   reflect(-lightDirection, normalDirection), 
173                   viewDirection)), _Shininess);
174             }
175  
176             output.col = float4(diffuseReflection 
177                + specularReflection, 1.0);
178                // no ambient contribution in this pass
179             output.pos = UnityObjectToClipPos(input.vertex);
180             return output;
181          }
182  
183          float4 frag(vertexOutput input) : COLOR
184          {
185             return input.col;
186          }
187  
188          ENDCG
189       }
190    }
191    Fallback "Specular"
192 }
Per-vertex lighting

Two-Sided Surfaces (about two-sided per-vertex lighting)

  1 Shader "Custom/Cg two-sided per-vertex lighting" {
  2    Properties {
  3       _Color ("Front Material Diffuse Color", Color) = (1,1,1,1) 
  4       _SpecColor ("Front Material Specular Color", Color) = (1,1,1,1) 
  5       _Shininess ("Front Material Shininess", Float) = 10
  6       _BackColor ("Back Material Diffuse Color", Color) = (1,1,1,1) 
  7       _BackSpecColor ("Back Material Specular Color", Color) 
  8          = (1,1,1,1) 
  9       _BackShininess ("Back Material Shininess", Float) = 10
 10    }
 11    SubShader {
 12       Pass {    
 13          Tags { "LightMode" = "ForwardBase" } 
 14             // pass for ambient light and first light source 
 15          Cull Back // render only front faces
 16  
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag 
 21  
 22          #include "UnityCG.cginc"
 23          uniform float4 _LightColor0; 
 24             // color of light source (from "Lighting.cginc")
 25  
 26          // User-specified properties
 27          uniform float4 _Color; 
 28          uniform float4 _SpecColor; 
 29          uniform float _Shininess;
 30          uniform float4 _BackColor; 
 31          uniform float4 _BackSpecColor; 
 32          uniform float _BackShininess;
 33  
 34          struct vertexInput {
 35             float4 vertex : POSITION;
 36             float3 normal : NORMAL;
 37          };
 38          struct vertexOutput {
 39             float4 pos : SV_POSITION;
 40             float4 col : COLOR;
 41          };
 42  
 43          vertexOutput vert(vertexInput input) 
 44          {
 45             vertexOutput output;
 46  
 47             float4x4 modelMatrix = _Object2World;
 48             float4x4 modelMatrixInverse = _World2Object; 
 49  
 50             float3 normalDirection = normalize(
 51                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 52             float3 viewDirection = normalize(_WorldSpaceCameraPos 
 53                - mul(modelMatrix, input.vertex).xyz);
 54             float3 lightDirection;
 55             float attenuation;
 56  
 57             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 58             {
 59                attenuation = 1.0; // no attenuation
 60                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 61             } 
 62             else // point or spot light
 63             {
 64                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
 65                   - mul(modelMatrix, input.vertex).xyz;
 66                float distance = length(vertexToLightSource);
 67                attenuation = 1.0 / distance; // linear attenuation 
 68                lightDirection = normalize(vertexToLightSource);
 69             }
 70  
 71             float3 ambientLighting = 
 72                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 73  
 74             float3 diffuseReflection = 
 75                attenuation * _LightColor0.rgb * _Color.rgb
 76                * max(0.0, dot(normalDirection, lightDirection));
 77  
 78             float3 specularReflection;
 79             if (dot(normalDirection, lightDirection) < 0.0) 
 80                // light source on the wrong side?
 81             {
 82                specularReflection = float3(0.0, 0.0, 0.0); 
 83                   // no specular reflection
 84             }
 85             else // light source on the right side
 86             {
 87                specularReflection = attenuation * _LightColor0.rgb 
 88                   * _SpecColor.rgb * pow(max(0.0, dot(
 89                   reflect(-lightDirection, normalDirection), 
 90                   viewDirection)), _Shininess);
 91             }
 92  
 93             output.col = float4(ambientLighting + diffuseReflection 
 94                + specularReflection, 1.0);
 95             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
 96             return output;
 97          }
 98  
 99          float4 frag(vertexOutput input) : COLOR
100          {
101             return input.col;
102          }
103  
104          ENDCG
105       }
106  
107       Pass {    
108          Tags { "LightMode" = "ForwardAdd" } 
109             // pass for additional light sources
110          Blend One One // additive blending 
111          Cull Back // render only front faces
112  
113          CGPROGRAM
114  
115          #pragma vertex vert  
116          #pragma fragment frag 
117  
118          #include "UnityCG.cginc"
119          uniform float4 _LightColor0; 
120             // color of light source (from "Lighting.cginc")
121  
122         // User-specified properties
123          uniform float4 _Color; 
124          uniform float4 _SpecColor; 
125          uniform float _Shininess;
126          uniform float4 _BackColor; 
127          uniform float4 _BackSpecColor; 
128          uniform float _BackShininess;
129  
130          struct vertexInput {
131             float4 vertex : POSITION;
132             float3 normal : NORMAL;
133          };
134          struct vertexOutput {
135             float4 pos : SV_POSITION;
136             float4 col : COLOR;
137          };
138  
139          vertexOutput vert(vertexInput input) 
140          {
141             vertexOutput output;
142  
143             float4x4 modelMatrix = _Object2World;
144             float4x4 modelMatrixInverse = _World2Object; 
145  
146             float3 normalDirection = normalize(
147                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
148             float3 viewDirection = normalize(_WorldSpaceCameraPos 
149                - mul(modelMatrix, input.vertex).xyz);
150             float3 lightDirection;
151             float attenuation;
152  
153             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
154             {
155                attenuation = 1.0; // no attenuation
156                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
157             } 
158             else // point or spot light
159             {
160                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
161                   - mul(modelMatrix, input.vertex).xyz;
162                float distance = length(vertexToLightSource);
163                attenuation = 1.0 / distance; // linear attenuation 
164                lightDirection = normalize(vertexToLightSource);
165             }
166  
167             float3 diffuseReflection = 
168                attenuation * _LightColor0.rgb * _Color.rgb
169                * max(0.0, dot(normalDirection, lightDirection));
170  
171             float3 specularReflection;
172             if (dot(normalDirection, lightDirection) < 0.0) 
173                // light source on the wrong side?
174             {
175                specularReflection = float3(0.0, 0.0, 0.0); 
176                   // no specular reflection
177             }
178             else // light source on the right side
179             {
180                specularReflection = attenuation * _LightColor0.rgb 
181                   * _SpecColor.rgb * pow(max(0.0, dot(
182                   reflect(-lightDirection, normalDirection), 
183                   viewDirection)), _Shininess);
184             }
185  
186             output.col = float4(diffuseReflection 
187                + specularReflection, 1.0);
188                // no ambient contribution in this pass
189             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
190             return output;
191          }
192  
193          float4 frag(vertexOutput input) : COLOR
194          {
195             return input.col;
196          }
197  
198          ENDCG
199       }
200  
201       Pass {    
202          Tags { "LightMode" = "ForwardBase" } 
203             // pass for ambient light and first light source 
204          Cull Front// render only back faces
205  
206          CGPROGRAM
207  
208          #pragma vertex vert  
209          #pragma fragment frag 
210  
211          #include "UnityCG.cginc"
212          uniform float4 _LightColor0; 
213             // color of light source (from "Lighting.cginc")
214  
215          // User-specified properties
216          uniform float4 _Color; 
217          uniform float4 _SpecColor; 
218          uniform float _Shininess;
219          uniform float4 _BackColor; 
220          uniform float4 _BackSpecColor; 
221          uniform float _BackShininess;
222  
223          struct vertexInput {
224             float4 vertex : POSITION;
225             float3 normal : NORMAL;
226          };
227          struct vertexOutput {
228             float4 pos : SV_POSITION;
229             float4 col : COLOR;
230          };
231  
232          vertexOutput vert(vertexInput input) 
233          {
234             vertexOutput output;
235  
236             float4x4 modelMatrix = _Object2World;
237             float4x4 modelMatrixInverse = _World2Object; 
238  
239             float3 normalDirection = normalize(
240                mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
241             float3 viewDirection = normalize(_WorldSpaceCameraPos 
242                - mul(modelMatrix, input.vertex).xyz);
243             float3 lightDirection;
244             float attenuation;
245  
246             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
247             {
248                attenuation = 1.0; // no attenuation
249                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
250             } 
251             else // point or spot light
252             {
253                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
254                   - mul(modelMatrix, input.vertex).xyz;
255                float distance = length(vertexToLightSource);
256                attenuation = 1.0 / distance; // linear attenuation 
257                lightDirection = normalize(vertexToLightSource);
258             }
259  
260             float3 ambientLighting = 
261                UNITY_LIGHTMODEL_AMBIENT.rgb * _BackColor.rgb;
262  
263             float3 diffuseReflection = 
264                attenuation * _LightColor0.rgb * _BackColor.rgb
265                * max(0.0, dot(normalDirection, lightDirection));
266  
267             float3 specularReflection;
268             if (dot(normalDirection, lightDirection) < 0.0) 
269                // light source on the wrong side?
270             {
271                specularReflection = float3(0.0, 0.0, 0.0); 
272                   // no specular reflection
273             }
274             else // light source on the right side
275             {
276                specularReflection = attenuation * _LightColor0.rgb 
277                   * _BackSpecColor.rgb * pow(max(0.0, dot(
278                   reflect(-lightDirection, normalDirection), 
279                   viewDirection)), _BackShininess);
280             }
281  
282             output.col = float4(ambientLighting + diffuseReflection 
283                + specularReflection, 1.0);
284             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
285             return output;
286          }
287  
288          float4 frag(vertexOutput input) : COLOR
289          {
290             return input.col;
291          }
292  
293          ENDCG
294       }
295  
296       Pass {    
297          Tags { "LightMode" = "ForwardAdd" } 
298             // pass for additional light sources
299          Blend One One // additive blending 
300          Cull Front // render only back faces
301  
302          CGPROGRAM
303  
304          #pragma vertex vert  
305          #pragma fragment frag 
306  
307          #include "UnityCG.cginc"
308          uniform float4 _LightColor0; 
309             // color of light source (from "Lighting.cginc")
310  
311         // User-specified properties
312          uniform float4 _Color; 
313          uniform float4 _SpecColor; 
314          uniform float _Shininess;
315          uniform float4 _BackColor; 
316          uniform float4 _BackSpecColor; 
317          uniform float _BackShininess;
318  
319          struct vertexInput {
320             float4 vertex : POSITION;
321             float3 normal : NORMAL;
322          };
323          struct vertexOutput {
324             float4 pos : SV_POSITION;
325             float4 col : COLOR;
326          };
327  
328          vertexOutput vert(vertexInput input) 
329          {
330             vertexOutput output;
331  
332             float4x4 modelMatrix = _Object2World;
333             float4x4 modelMatrixInverse = _World2Object; 
334  
335             float3 normalDirection = normalize(
336                mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
337             float3 viewDirection = normalize(_WorldSpaceCameraPos 
338                - mul(modelMatrix, input.vertex).xyz);
339             float3 lightDirection;
340             float attenuation;
341  
342             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
343             {
344                attenuation = 1.0; // no attenuation
345                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
346             } 
347             else // point or spot light
348             {
349                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
350                   - mul(modelMatrix, input.vertex).xyz;
351                float distance = length(vertexToLightSource);
352                attenuation = 1.0 / distance; // linear attenuation 
353                lightDirection = normalize(vertexToLightSource);
354             }
355  
356             float3 diffuseReflection = 
357                attenuation * _LightColor0.rgb * _BackColor.rgb
358                * max(0.0, dot(normalDirection, lightDirection));
359  
360             float3 specularReflection;
361             if (dot(normalDirection, lightDirection) < 0.0) 
362                // light source on the wrong side?
363             {
364                specularReflection = float3(0.0, 0.0, 0.0); 
365                   // no specular reflection
366             }
367             else // light source on the right side
368             {
369                specularReflection = attenuation * _LightColor0.rgb 
370                   * _BackSpecColor.rgb * pow(max(0.0, dot(
371                   reflect(-lightDirection, normalDirection), 
372                   viewDirection)), _BackShininess);
373             }
374  
375             output.col = float4(diffuseReflection 
376                + specularReflection, 1.0);
377                // no ambient contribution in this pass
378             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
379             return output;
380          }
381  
382          float4 frag(vertexOutput input) : COLOR
383          {
384             return input.col;
385          }
386  
387          ENDCG
388       }
389  
390    }
391    Fallback "Specular"
392 }
Two-sided per-vertex lighting

Smooth Specular Highlights(about per-pixel lighting)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  6 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  7 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  8 
  9 Shader "Custom/Cg per-pixel lighting" {
 10     Properties {
 11         _Color("Diffuse Material Color",Color) = (1,1,1,1)
 12         _SpecColor("Specular Material Color",Color) = (1,1,1,1)
 13         _Shininess("Shininess",Float) = 10
 14     }
 15     SubShader {
 16         // pass for ambient light and first light source
 17         Pass {
 18             Tags { "LihgtMode" = "ForwardBase" }
 19 
 20             CGPROGRAM
 21 
 22             #pragma vertex vert
 23             #pragma fragment frag
 24 
 25             #include "UnityCG.cginc"
 26             
 27             uniform float4 _LightColor0;    // color of light source(from "Lighting.cginc")
 28 
 29             // User-specified Properties
 30             uniform float4 _Color;
 31             uniform float4 _SpecColor;
 32             uniform float _Shininess;
 33 
 34             struct vertexInput{
 35                 float4 vertex:POSITION;
 36                 float3 normal:NORMAL;
 37             };
 38             struct vertexOutput{
 39                 float4 pos:SV_POSITION;
 40                 float4 posWorld:TEXCOORD0;
 41                 float3 normalDir:TEXCOORD1;
 42             };
 43 
 44             vertexOutput vert(vertexInput input){
 45                 vertexOutput output;
 46 
 47                 float4x4 modelMatrix = unity_ObjectToWorld;
 48                 float4x4 modelMatrixInverse = unity_WorldToObject;
 49 
 50                 output.posWorld = mul(modelMatrix,input.vertex);
 51                 output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
 52                 output.pos = UnityObjectToClipPos(input.vertex);
 53 
 54                 return output;
 55             }
 56 
 57             float4 frag(vertexOutput input):COLOR{
 58                 float3 normalDirection = normalize(input.normalDir);
 59 
 60                 float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
 61                 float3 lightDirection;
 62                 float attenuation;
 63 
 64                 if(_WorldSpaceLightPos0.w == 0.0) { // directional light
 65                     attenuation = 1.0;    // no attenuation;
 66                     lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 67                 } else { // point on spot light
 68                     float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 69                     float distance = length(vertexToLightSource);
 70                     attenuation = 1.0/distance;    // linear attenuation;
 71                     lightDirection = normalize(vertexToLightSource);
 72                 }
 73 
 74                 float3 ambientLighting = UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 75 
 76                 float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
 77 
 78                 float3 specularReflection;
 79                 if(dot(normalDirection,lightDirection) < 0.0){    // light source on the wrong side?
 80                     // no specular reflection
 81                     specularReflection = float3(0.0,0.0,0.0);
 82                 } else {    // light source on the right side
 83                     specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0,dot(reflect(-lightDirection,normalDirection),viewDirection)),_Shininess);
 84                 }
 85 
 86                 return float4(ambientLighting + diffuseReflection + specularReflection,1.0);
 87             }
 88 
 89             ENDCG
 90         }
 91         // pass for additional light source
 92         Pass {
 93             Tags { "LightMode" = "ForwardAdd" }
 94 
 95             Blend One One // additive blending
 96 
 97             CGPROGRAM
 98 
 99             #pragma vertex vert
100             #pragma fragment frag
101 
102             #include "UnityCG.cginc"
103             uniform float4 _LightColor0;    // color of light source(from "Lighting.cginc")
104 
105             // User-specified properties
106             uniform float4 _Color;
107             uniform float4 _SpecColor;
108             uniform float _Shininess;
109 
110             struct vertexInput {
111                 float4 vertex:POSITION;
112                 float3 normal:NORMAL;
113             };
114             struct vertexOutput {
115                 float4 pos:SV_POSITION;
116                 float4 posWorld:TEXCOORD0;
117                 float3 normalDir:TEXCOORD1;
118             };
119 
120             vertexOutput vert(vertexInput input){
121                 vertexOutput output;
122 
123                 float4x4 modelMatrix = unity_ObjectToWorld;
124                 float4x4 modelMatrixInverse = unity_WorldToObject;
125 
126                 output.posWorld = mul(modelMatrix,input.vertex);
127                 output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
128                 output.pos = UnityObjectToClipPos(input.vertex);
129                 return output;
130             }
131 
132             float4 frag(vertexOutput input):COLOR{
133                 float3 normalDirection = normalize(input.normalDir);
134 
135                 float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
136                 float3 lightDirection;
137                 float attenuation;
138 
139                 if(_WorldSpaceLightPos0.w == 0.0){    // directional light
140                     attenuation = 1.0;    // no attenuation
141                     lightDirection = normalize(_WorldSpaceLightPos0.xyz);
142                 } else {    // point or spot light
143                     float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
144                     float distance = length(vertexToLightSource);
145                     attenuation = 1.0 / distance;    // linear attenuation
146                     lightDirection = normalize(vertexToLightSource);
147                 }
148 
149                 float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection));
150 
151                 float3 specularReflection;
152                 if(dot(normalDirection,lightDirection) < 0.0){    // light source on the wrong side?
153                     // no specular reflection
154                     specularReflection = float3(0.0,0.0,0.0);
155                 } else { // light source on the right side
156                     specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0,dot(reflect(-lightDirection,normalDirection),viewDirection)),_Shininess);
157                 }
158                 //no ambient lighting in this pass
159                 return float4(diffuseReflection + specularReflection,1.0);
160             }
161 
162             ENDCG
163         }
164     }
165 
166     Fallback "Diffuse"
167 }
Per-pixel Lighting

Two-Sided Smooth Surfaces (about two-sided per-pixel lighting)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg two-sided per-pixel lighting" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _Shininess ("Shininess", Float) = 10
 10       _BackColor ("Back Material Diffuse Color", Color) = (1,1,1,1) 
 11       _BackSpecColor ("Back Material Specular Color", Color) 
 12          = (1,1,1,1) 
 13       _BackShininess ("Back Material Shininess", Float) = 10
 14    }
 15    SubShader {
 16       Pass {    
 17          Tags { "LightMode" = "ForwardBase" } 
 18             // pass for ambient light and first light source
 19          Cull Back // render only front faces
 20  
 21          CGPROGRAM
 22  
 23          #pragma vertex vert  
 24          #pragma fragment frag 
 25  
 26          #include "UnityCG.cginc"
 27          uniform float4 _LightColor0; 
 28             // color of light source (from "Lighting.cginc")
 29  
 30          // User-specified properties
 31          uniform float4 _Color; 
 32          uniform float4 _SpecColor; 
 33          uniform float _Shininess;
 34          uniform float4 _BackColor; 
 35          uniform float4 _BackSpecColor; 
 36          uniform float _BackShininess;
 37  
 38          struct vertexInput {
 39             float4 vertex : POSITION;
 40             float3 normal : NORMAL;
 41          };
 42          struct vertexOutput {
 43             float4 pos : SV_POSITION;
 44             float4 posWorld : TEXCOORD0;
 45             float3 normalDir : TEXCOORD1;
 46          };
 47  
 48          vertexOutput vert(vertexInput input) 
 49          {
 50             vertexOutput output;
 51  
 52             float4x4 modelMatrix = unity_ObjectToWorld;
 53             float4x4 modelMatrixInverse = unity_WorldToObject; 
 54  
 55             output.posWorld = mul(modelMatrix, input.vertex);
 56             output.normalDir = normalize(
 57                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 58             output.pos = UnityObjectToClipPos(input.vertex);
 59             return output;
 60          }
 61  
 62          float4 frag(vertexOutput input) : COLOR
 63          {
 64             float3 normalDirection = normalize(input.normalDir);
 65  
 66             float3 viewDirection = normalize(
 67                _WorldSpaceCameraPos - input.posWorld.xyz);
 68             float3 lightDirection;
 69             float attenuation;
 70  
 71             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 72             {
 73                attenuation = 1.0; // no attenuation
 74                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 75             } 
 76             else // point or spot light
 77             {
 78                float3 vertexToLightSource = 
 79                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 80                float distance = length(vertexToLightSource);
 81                attenuation = 1.0 / distance; // linear attenuation 
 82                lightDirection = normalize(vertexToLightSource);
 83             }
 84  
 85             float3 ambientLighting = 
 86                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 87  
 88             float3 diffuseReflection = 
 89                attenuation * _LightColor0.rgb * _Color.rgb
 90                * max(0.0, dot(normalDirection, lightDirection));
 91  
 92             float3 specularReflection;
 93             if (dot(normalDirection, lightDirection) < 0.0) 
 94                // light source on the wrong side?
 95             {
 96                specularReflection = float3(0.0, 0.0, 0.0); 
 97                   // no specular reflection
 98             }
 99             else // light source on the right side
100             {
101                specularReflection = attenuation * _LightColor0.rgb 
102                   * _SpecColor.rgb * pow(max(0.0, dot(
103                   reflect(-lightDirection, normalDirection), 
104                   viewDirection)), _Shininess);
105             }
106  
107             return float4(ambientLighting + diffuseReflection 
108                + specularReflection, 1.0);
109          }
110  
111          ENDCG
112       }
113  
114       Pass {    
115          Tags { "LightMode" = "ForwardAdd" } 
116             // pass for additional light sources
117          Blend One One // additive blending 
118          Cull Back // render only front faces
119  
120          CGPROGRAM
121  
122          #pragma vertex vert  
123          #pragma fragment frag 
124  
125          #include "UnityCG.cginc"
126          uniform float4 _LightColor0; 
127             // color of light source (from "Lighting.cginc")
128  
129          // User-specified properties
130          uniform float4 _Color; 
131          uniform float4 _SpecColor; 
132          uniform float _Shininess;
133          uniform float4 _BackColor; 
134          uniform float4 _BackSpecColor; 
135          uniform float _BackShininess;
136  
137          struct vertexInput {
138             float4 vertex : POSITION;
139             float3 normal : NORMAL;
140          };
141          struct vertexOutput {
142             float4 pos : SV_POSITION;
143             float4 posWorld : TEXCOORD0;
144             float3 normalDir : TEXCOORD1;
145          };
146  
147          vertexOutput vert(vertexInput input) 
148          {
149             vertexOutput output;
150  
151             float4x4 modelMatrix = unity_ObjectToWorld;
152             float4x4 modelMatrixInverse = unity_WorldToObject; 
153  
154             output.posWorld = mul(modelMatrix, input.vertex);
155             output.normalDir = normalize(
156                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
157             output.pos = UnityObjectToClipPos(input.vertex);
158             return output;
159          }
160  
161          float4 frag(vertexOutput input) : COLOR
162          {
163             float3 normalDirection = normalize(input.normalDir);
164  
165             float3 viewDirection = normalize(
166                _WorldSpaceCameraPos - input.posWorld.xyz);
167             float3 lightDirection;
168             float attenuation;
169  
170             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
171             {
172                attenuation = 1.0; // no attenuation
173                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
174             } 
175             else // point or spot light
176             {
177                float3 vertexToLightSource = 
178                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
179                float distance = length(vertexToLightSource);
180                attenuation = 1.0 / distance; // linear attenuation 
181                lightDirection = normalize(vertexToLightSource);
182             }
183  
184             float3 diffuseReflection = 
185                attenuation * _LightColor0.rgb * _Color.rgb
186                * max(0.0, dot(normalDirection, lightDirection));
187  
188             float3 specularReflection;
189             if (dot(normalDirection, lightDirection) < 0.0) 
190                // light source on the wrong side?
191             {
192                specularReflection = float3(0.0, 0.0, 0.0); 
193                   // no specular reflection
194             }
195             else // light source on the right side
196             {
197                specularReflection = attenuation * _LightColor0.rgb 
198                   * _SpecColor.rgb * pow(max(0.0, dot(
199                   reflect(-lightDirection, normalDirection), 
200                   viewDirection)), _Shininess);
201             }
202  
203             return float4(diffuseReflection 
204                + specularReflection, 1.0);
205                // no ambient lighting in this pass
206          }
207  
208          ENDCG
209       }
210  
211       Pass {    
212          Tags { "LightMode" = "ForwardBase" } 
213             // pass for ambient light and first light source
214          Cull Front // render only back faces
215  
216          CGPROGRAM
217  
218          #pragma vertex vert  
219          #pragma fragment frag 
220  
221          #include "UnityCG.cginc"
222          uniform float4 _LightColor0; 
223             // color of light source (from "Lighting.cginc")
224  
225          // User-specified properties
226          uniform float4 _Color; 
227          uniform float4 _SpecColor; 
228          uniform float _Shininess;
229          uniform float4 _BackColor; 
230          uniform float4 _BackSpecColor; 
231          uniform float _BackShininess;
232  
233          struct vertexInput {
234             float4 vertex : POSITION;
235             float3 normal : NORMAL;
236          };
237          struct vertexOutput {
238             float4 pos : SV_POSITION;
239             float4 posWorld : TEXCOORD0;
240             float3 normalDir : TEXCOORD1;
241          };
242  
243          vertexOutput vert(vertexInput input) 
244          {
245             vertexOutput output;
246  
247             float4x4 modelMatrix = unity_ObjectToWorld;
248             float4x4 modelMatrixInverse = unity_WorldToObject; 
249  
250             output.posWorld = mul(modelMatrix, input.vertex);
251             output.normalDir = normalize(
252                mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
253             output.pos = UnityObjectToClipPos(input.vertex);
254             return output;
255          }
256  
257          float4 frag(vertexOutput input) : COLOR
258          {
259             float3 normalDirection = normalize(input.normalDir);
260  
261             float3 viewDirection = normalize(
262                _WorldSpaceCameraPos - input.posWorld.xyz);
263             float3 lightDirection;
264             float attenuation;
265  
266             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
267             {
268                attenuation = 1.0; // no attenuation
269                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
270             } 
271             else // point or spot light
272             {
273                float3 vertexToLightSource = 
274                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
275                float distance = length(vertexToLightSource);
276                attenuation = 1.0 / distance; // linear attenuation 
277                lightDirection = normalize(vertexToLightSource);
278             }
279  
280             float3 ambientLighting = 
281                UNITY_LIGHTMODEL_AMBIENT.rgb * _BackColor.rgb;
282  
283             float3 diffuseReflection = 
284                attenuation * _LightColor0.rgb * _BackColor.rgb
285                * max(0.0, dot(normalDirection, lightDirection));
286  
287             float3 specularReflection;
288             if (dot(normalDirection, lightDirection) < 0.0) 
289                // light source on the wrong side?
290             {
291                specularReflection = float3(0.0, 0.0, 0.0); 
292                   // no specular reflection
293             }
294             else // light source on the right side
295             {
296                specularReflection = attenuation * _LightColor0.rgb 
297                   * _BackSpecColor.rgb * pow(max(0.0, dot(
298                   reflect(-lightDirection, normalDirection), 
299                   viewDirection)), _BackShininess);
300             }
301  
302             return float4(ambientLighting + diffuseReflection 
303                + specularReflection, 1.0);
304          }
305  
306          ENDCG
307       }
308  
309       Pass {    
310          Tags { "LightMode" = "ForwardAdd" } 
311             // pass for additional light sources
312          Blend One One // additive blending 
313          Cull Front // render only back faces
314  
315          CGPROGRAM
316  
317          #pragma vertex vert  
318          #pragma fragment frag 
319  
320          #include "UnityCG.cginc"
321          uniform float4 _LightColor0; 
322             // color of light source (from "Lighting.cginc")
323  
324          // User-specified properties
325          uniform float4 _Color; 
326          uniform float4 _SpecColor; 
327          uniform float _Shininess;
328          uniform float4 _BackColor; 
329          uniform float4 _BackSpecColor; 
330          uniform float _BackShininess;
331  
332          struct vertexInput {
333             float4 vertex : POSITION;
334             float3 normal : NORMAL;
335          };
336          struct vertexOutput {
337             float4 pos : SV_POSITION;
338             float4 posWorld : TEXCOORD0;
339             float3 normalDir : TEXCOORD1;
340          };
341  
342          vertexOutput vert(vertexInput input) 
343          {
344             vertexOutput output;
345  
346             float4x4 modelMatrix = unity_ObjectToWorld;
347             float4x4 modelMatrixInverse = unity_WorldToObject; 
348  
349             output.posWorld = mul(modelMatrix, input.vertex);
350             output.normalDir = normalize(
351                mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
352             output.pos = UnityObjectToClipPos(input.vertex);
353             return output;
354          }
355  
356          float4 frag(vertexOutput input) : COLOR
357          {
358             float3 normalDirection = normalize(input.normalDir);
359  
360             float3 viewDirection = normalize(
361                _WorldSpaceCameraPos - input.posWorld.xyz);
362             float3 lightDirection;
363             float attenuation;
364  
365             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
366             {
367                attenuation = 1.0; // no attenuation
368                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
369             } 
370             else // point or spot light
371             {
372                float3 vertexToLightSource = 
373                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
374                float distance = length(vertexToLightSource);
375                attenuation = 1.0 / distance; // linear attenuation 
376                lightDirection = normalize(vertexToLightSource);
377             }
378  
379             float3 diffuseReflection = 
380                attenuation * _LightColor0.rgb * _BackColor.rgb
381                * max(0.0, dot(normalDirection, lightDirection));
382  
383             float3 specularReflection;
384             if (dot(normalDirection, lightDirection) < 0.0) 
385                // light source on the wrong side?
386             {
387                specularReflection = float3(0.0, 0.0, 0.0); 
388                   // no specular reflection
389             }
390             else // light source on the right side
391             {
392                specularReflection = attenuation * _LightColor0.rgb 
393                   * _BackSpecColor.rgb * pow(max(0.0, dot(
394                   reflect(-lightDirection, normalDirection), 
395                   viewDirection)), _BackShininess);
396             }
397  
398             return float4(diffuseReflection 
399                + specularReflection, 1.0);
400                // no ambient lighting in this pass
401          }
402  
403          ENDCG
404       }
405  
406    }
407    Fallback "Specular"
408 }
Two-sided per-pixel lighting

Multiple Lights (about for-loops for handling multiple light sources in one shader pass)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg per-pixel lighting with vertex lights" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _Shininess ("Shininess", Float) = 10
 10    }
 11    SubShader {
 12       Pass {      
 13          Tags { "LightMode" = "ForwardBase" } // pass for 
 14             // 4 vertex lights, ambient light & first pixel light
 15  
 16          CGPROGRAM
 17          #pragma multi_compile_fwdbase 
 18          #pragma vertex vert
 19          #pragma fragment frag
 20  
 21          #include "UnityCG.cginc" 
 22          uniform float4 _LightColor0; 
 23             // color of light source (from "Lighting.cginc")
 24  
 25          // User-specified properties
 26          uniform float4 _Color; 
 27          uniform float4 _SpecColor; 
 28          uniform float _Shininess;
 29  
 30          struct vertexInput {
 31             float4 vertex : POSITION;
 32             float3 normal : NORMAL;
 33          };
 34          struct vertexOutput {
 35             float4 pos : SV_POSITION;
 36             float4 posWorld : TEXCOORD0;
 37             float3 normalDir : TEXCOORD1;
 38             float3 vertexLighting : TEXCOORD2;
 39          };
 40  
 41          vertexOutput vert(vertexInput input)
 42          {          
 43             vertexOutput output;
 44  
 45             float4x4 modelMatrix = unity_ObjectToWorld;
 46             float4x4 modelMatrixInverse = unity_WorldToObject; 
 47  
 48             output.posWorld = mul(modelMatrix, input.vertex);
 49             output.normalDir = normalize(
 50                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 51             output.pos = UnityObjectToClipPos(input.vertex);
 52  
 53             // Diffuse reflection by four "vertex lights"            
 54             output.vertexLighting = float3(0.0, 0.0, 0.0);
 55             #ifdef VERTEXLIGHT_ON
 56             for (int index = 0; index < 4; index++)
 57             {    
 58                float4 lightPosition = float4(unity_4LightPosX0[index], 
 59                   unity_4LightPosY0[index], 
 60                   unity_4LightPosZ0[index], 1.0);
 61  
 62                float3 vertexToLightSource = 
 63                   lightPosition.xyz - output.posWorld.xyz;        
 64                float3 lightDirection = normalize(vertexToLightSource);
 65                float squaredDistance = 
 66                   dot(vertexToLightSource, vertexToLightSource);
 67                float attenuation = 1.0 / (1.0 + 
 68                   unity_4LightAtten0[index] * squaredDistance);
 69                float3 diffuseReflection = attenuation 
 70                   * unity_LightColor[index].rgb * _Color.rgb 
 71                   * max(0.0, dot(output.normalDir, lightDirection));         
 72  
 73                output.vertexLighting = 
 74                   output.vertexLighting + diffuseReflection;
 75             }
 76             #endif
 77             return output;
 78          }
 79  
 80          float4 frag(vertexOutput input) : COLOR
 81          {
 82             float3 normalDirection = normalize(input.normalDir); 
 83             float3 viewDirection = normalize(
 84                _WorldSpaceCameraPos - input.posWorld.xyz);
 85             float3 lightDirection;
 86             float attenuation;
 87  
 88             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 89             {
 90                attenuation = 1.0; // no attenuation
 91                lightDirection = 
 92                   normalize(_WorldSpaceLightPos0.xyz);
 93             } 
 94             else // point or spot light
 95             {
 96                float3 vertexToLightSource = 
 97                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 98                float distance = length(vertexToLightSource);
 99                attenuation = 1.0 / distance; // linear attenuation 
100                lightDirection = normalize(vertexToLightSource);
101             }
102  
103             float3 ambientLighting = 
104                 UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
105  
106             float3 diffuseReflection = 
107                attenuation * _LightColor0.rgb * _Color.rgb 
108                * max(0.0, dot(normalDirection, lightDirection));
109  
110             float3 specularReflection;
111             if (dot(normalDirection, lightDirection) < 0.0) 
112                // light source on the wrong side?
113             {
114                specularReflection = float3(0.0, 0.0, 0.0); 
115                   // no specular reflection
116             }
117             else // light source on the right side
118             {
119                specularReflection = attenuation * _LightColor0.rgb 
120                   * _SpecColor.rgb * pow(max(0.0, dot(
121                   reflect(-lightDirection, normalDirection), 
122                   viewDirection)), _Shininess);
123             }
124  
125             return float4(input.vertexLighting + ambientLighting 
126                + diffuseReflection + specularReflection, 1.0);
127          }
128          ENDCG
129       }
130  
131       Pass {    
132          Tags { "LightMode" = "ForwardAdd" } 
133             // pass for additional light sources
134          Blend One One // additive blending 
135  
136           CGPROGRAM
137  
138          #pragma vertex vert  
139          #pragma fragment frag 
140  
141          #include "UnityCG.cginc" 
142          uniform float4 _LightColor0; 
143             // color of light source (from "Lighting.cginc")
144  
145          // User-specified properties
146          uniform float4 _Color; 
147          uniform float4 _SpecColor; 
148          uniform float _Shininess;
149  
150          struct vertexInput {
151             float4 vertex : POSITION;
152             float3 normal : NORMAL;
153          };
154          struct vertexOutput {
155             float4 pos : SV_POSITION;
156             float4 posWorld : TEXCOORD0;
157             float3 normalDir : TEXCOORD1;
158          };
159  
160          vertexOutput vert(vertexInput input) 
161          {
162             vertexOutput output;
163  
164             float4x4 modelMatrix = unity_ObjectToWorld;
165             float4x4 modelMatrixInverse = unity_WorldToObject; 
166  
167             output.posWorld = mul(modelMatrix, input.vertex);
168             output.normalDir = normalize(
169                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
170             output.pos = UnityObjectToClipPos(input.vertex);
171             return output;
172          }
173  
174          float4 frag(vertexOutput input) : COLOR
175          {
176             float3 normalDirection = normalize(input.normalDir);
177  
178             float3 viewDirection = normalize(
179                _WorldSpaceCameraPos.xyz - input.posWorld.xyz);
180             float3 lightDirection;
181             float attenuation;
182  
183             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
184             {
185                attenuation = 1.0; // no attenuation
186                lightDirection = 
187                   normalize(_WorldSpaceLightPos0.xyz);
188             } 
189             else // point or spot light
190             {
191                float3 vertexToLightSource = 
192                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
193                float distance = length(vertexToLightSource);
194                attenuation = 1.0 / distance; // linear attenuation 
195                lightDirection = normalize(vertexToLightSource);
196             }
197  
198             float3 diffuseReflection = 
199                attenuation * _LightColor0.rgb * _Color.rgb
200                * max(0.0, dot(normalDirection, lightDirection));
201  
202             float3 specularReflection;
203             if (dot(normalDirection, lightDirection) < 0.0) 
204                // light source on the wrong side?
205             {
206                specularReflection = float3(0.0, 0.0, 0.0); 
207                   // no specular reflection
208             }
209             else // light source on the right side
210             {
211                specularReflection = attenuation * _LightColor0.rgb 
212                   * _SpecColor.rgb * pow(max(0.0, dot(
213                   reflect(-lightDirection, normalDirection), 
214                   viewDirection)), _Shininess);
215             }
216  
217             return float4(diffuseReflection 
218                + specularReflection, 1.0);
219                // no ambient lighting in this pass
220          }
221  
222          ENDCG
223       }
224  
225    } 
226    Fallback "Specular"
227 }
Per-pixel lighting with vertex lights

Basic Texturing

Textured Spheres (about texturing a sphere)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg shader with single texture" {
 4    Properties {
 5       _MainTex ("Texture Image", 2D) = "white" {} 
 6          // a 2D texture property that we call "_MainTex", which should
 7          // be labeled "Texture Image" in Unity's user interface.
 8          // By default we use the built-in texture "white"  
 9          // (alternatives: "black", "gray" and "bump").
10    }
11    SubShader {
12       Pass {    
13          CGPROGRAM
14  
15          #pragma vertex vert  
16          #pragma fragment frag 
17  
18          uniform sampler2D _MainTex;    
19             // a uniform variable refering to the property above
20             // (in fact, this is just a small integer specifying a 
21             // "texture unit", which has the texture image "bound" 
22             // to it; Unity takes care of this).
23  
24          struct vertexInput {
25             float4 vertex : POSITION;
26             float4 texcoord : TEXCOORD0;
27          };
28          struct vertexOutput {
29             float4 pos : SV_POSITION;
30             float4 tex : TEXCOORD0;
31          };
32  
33          vertexOutput vert(vertexInput input) 
34          {
35             vertexOutput output;
36  
37             output.tex = input.texcoord;
38                // Unity provides default longitude-latitude-like 
39                // texture coordinates at all vertices of a 
40                // sphere mesh as the input parameter 
41                // "input.texcoord" with semantic "TEXCOORD0".
42             output.pos = UnityObjectToClipPos(input.vertex);
43             return output;
44          }
45          float4 frag(vertexOutput input) : COLOR
46          {
47             return tex2D(_MainTex, input.tex.xy);    
48                // look up the color of the texture image specified by 
49                // the uniform "_MainTex" at the position specified by 
50                // "input.tex.x" and "input.tex.y" and return it
51  
52          }
53  
54          ENDCG
55       }
56    }
57    Fallback "Unlit/Texture"
58 }
Shader with single texture

Lighting Textured Surfaces (about textures for diffuse lighting)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg per-vertex lighting with texture" {
  6    Properties {
  7       _MainTex ("Texture For Diffuse Material Color", 2D) = "white" {} 
  8       _Color ("Overall Diffuse Color Filter", Color) = (1,1,1,1)
  9       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
 10       _Shininess ("Shininess", Float) = 10
 11    }
 12    SubShader {
 13       Pass {    
 14          Tags { "LightMode" = "ForwardBase" } 
 15             // pass for ambient light and first light source
 16  
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag
 21  
 22          #include "UnityCG.cginc" 
 23          uniform float4 _LightColor0; 
 24             // color of light source (from "Lighting.cginc")
 25  
 26          // User-specified properties
 27          uniform sampler2D _MainTex;    
 28          uniform float4 _Color; 
 29          uniform float4 _SpecColor; 
 30          uniform float _Shininess;
 31  
 32          struct vertexInput {
 33             float4 vertex : POSITION;
 34             float3 normal : NORMAL;
 35             float4 texcoord : TEXCOORD0;
 36          };
 37          struct vertexOutput {
 38             float4 pos : SV_POSITION;
 39             float4 tex : TEXCOORD0;
 40             float3 diffuseColor : TEXCOORD1;
 41             float3 specularColor : TEXCOORD2;
 42          };
 43  
 44          vertexOutput vert(vertexInput input) 
 45          {
 46             vertexOutput output;
 47  
 48             float4x4 modelMatrix = unity_ObjectToWorld;
 49             float4x4 modelMatrixInverse = unity_WorldToObject; 
 50  
 51             float3 normalDirection = normalize(
 52                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 53             float3 viewDirection = normalize(_WorldSpaceCameraPos 
 54                - mul(modelMatrix, input.vertex).xyz);
 55             float3 lightDirection;
 56             float attenuation;
 57  
 58             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 59             {
 60                attenuation = 1.0; // no attenuation
 61                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 62             } 
 63             else // point or spot light
 64             {
 65                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
 66                   - mul(modelMatrix, input.vertex).xyz;
 67                float distance = length(vertexToLightSource);
 68                attenuation = 1.0 / distance; // linear attenuation 
 69                lightDirection = normalize(vertexToLightSource);
 70             }
 71  
 72             float3 ambientLighting = 
 73                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 74  
 75             float3 diffuseReflection = 
 76                attenuation * _LightColor0.rgb * _Color.rgb
 77                * max(0.0, dot(normalDirection, lightDirection));
 78  
 79             float3 specularReflection;
 80             if (dot(normalDirection, lightDirection) < 0.0) 
 81                // light source on the wrong side?
 82             {
 83                specularReflection = float3(0.0, 0.0, 0.0); 
 84                   // no specular reflection
 85             }
 86             else // light source on the right side
 87             {
 88                specularReflection = attenuation * _LightColor0.rgb 
 89                   * _SpecColor.rgb * pow(max(0.0, dot(
 90                   reflect(-lightDirection, normalDirection), 
 91                   viewDirection)), _Shininess);
 92             }
 93  
 94             output.diffuseColor = ambientLighting + diffuseReflection;
 95             output.specularColor = specularReflection;
 96             output.tex = input.texcoord;
 97             output.pos = UnityObjectToClipPos(input.vertex);
 98             return output;
 99          }
100  
101          float4 frag(vertexOutput input) : COLOR
102          {
103             return float4(input.specularColor +
104                input.diffuseColor * tex2D(_MainTex, input.tex.xy),
105                1.0);
106          }
107  
108          ENDCG
109       }
110  
111       Pass {    
112          Tags { "LightMode" = "ForwardAdd" } 
113             // pass for additional light sources
114          Blend One One // additive blending 
115  
116          CGPROGRAM
117  
118          #pragma vertex vert  
119          #pragma fragment frag 
120  
121          #include "UnityCG.cginc" 
122          uniform float4 _LightColor0; 
123             // color of light source (from "Lighting.cginc")
124  
125          // User-specified properties
126          uniform sampler2D _MainTex;    
127          uniform float4 _Color; 
128          uniform float4 _SpecColor; 
129          uniform float _Shininess;
130  
131          struct vertexInput {
132             float4 vertex : POSITION;
133             float3 normal : NORMAL;
134             float4 texcoord : TEXCOORD0;
135          };
136          struct vertexOutput {
137             float4 pos : SV_POSITION;
138             float4 tex : TEXCOORD0;
139             float3 diffuseColor : TEXCOORD1;
140             float3 specularColor : TEXCOORD2;
141          };
142  
143          vertexOutput vert(vertexInput input) 
144          {
145             vertexOutput output;
146  
147             float4x4 modelMatrix = unity_ObjectToWorld;
148             float4x4 modelMatrixInverse = unity_WorldToObject;
149  
150             float3 normalDirection = normalize(
151                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
152             float3 viewDirection = normalize(_WorldSpaceCameraPos 
153                - mul(modelMatrix, input.vertex).xyz);
154             float3 lightDirection;
155             float attenuation;
156  
157             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
158             {
159                attenuation = 1.0; // no attenuation
160                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
161             } 
162             else // point or spot light
163             {
164                float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
165                   - mul(modelMatrix, input.vertex).xyz;
166                float distance = length(vertexToLightSource);
167                attenuation = 1.0 / distance; // linear attenuation 
168                lightDirection = normalize(vertexToLightSource);
169             }
170  
171             float3 diffuseReflection = 
172                attenuation * _LightColor0.rgb * _Color.rgb
173                * max(0.0, dot(normalDirection, lightDirection));
174  
175             float3 specularReflection;
176             if (dot(normalDirection, lightDirection) < 0.0) 
177                // light source on the wrong side?
178             {
179                specularReflection = float3(0.0, 0.0, 0.0); 
180                   // no specular reflection
181             }
182             else // light source on the right side
183             {
184                specularReflection = attenuation * _LightColor0.rgb 
185                   * _SpecColor.rgb * pow(max(0.0, dot(
186                   reflect(-lightDirection, normalDirection), 
187                   viewDirection)), _Shininess);
188             }
189  
190             output.diffuseColor = diffuseReflection; // no ambient
191             output.specularColor = specularReflection;
192             output.tex = input.texcoord;
193             output.pos = UnityObjectToClipPos(input.vertex);
194             return output;
195          }
196  
197          float4 frag(vertexOutput input) : COLOR
198          {
199             return float4(input.specularColor +
200                input.diffuseColor * tex2D(_MainTex, input.tex.xy),
201                1.0);
202          }
203  
204          ENDCG
205       }
206    }
207    Fallback "Specular"
208 }
Per-vertex lighting with texture

Glossy Textures (about gloss mapping)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg per-pixel lighting with texture" {
  6    Properties {
  7       _MainTex ("RGBA Texture For Material Color", 2D) = "white" {} 
  8       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  9       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
 10       _Shininess ("Shininess", Float) = 10
 11    }
 12    SubShader {
 13       Pass {    
 14          Tags { "LightMode" = "ForwardBase" } 
 15             // pass for ambient light and first light source
 16  
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag 
 21  
 22          #include "UnityCG.cginc"
 23          uniform float4 _LightColor0; 
 24             // color of light source (from "Lighting.cginc")
 25  
 26          // User-specified properties
 27          uniform sampler2D _MainTex;    
 28          uniform float4 _Color; 
 29          uniform float4 _SpecColor; 
 30          uniform float _Shininess;
 31  
 32          struct vertexInput {
 33             float4 vertex : POSITION;
 34             float3 normal : NORMAL;
 35             float4 texcoord : TEXCOORD0;
 36         };
 37          struct vertexOutput {
 38             float4 pos : SV_POSITION;
 39             float4 posWorld : TEXCOORD0;
 40             float3 normalDir : TEXCOORD1;
 41             float4 tex : TEXCOORD2;
 42         };
 43  
 44          vertexOutput vert(vertexInput input) 
 45          {
 46             vertexOutput output;
 47  
 48             float4x4 modelMatrix = unity_ObjectToWorld;
 49             float4x4 modelMatrixInverse = unity_WorldToObject;
 50  
 51             output.posWorld = mul(modelMatrix, input.vertex);
 52             output.normalDir = normalize(
 53                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 54             output.tex = input.texcoord;
 55             output.pos = UnityObjectToClipPos(input.vertex);
 56             return output;
 57          }
 58  
 59          float4 frag(vertexOutput input) : COLOR
 60          {
 61             float3 normalDirection = normalize(input.normalDir);
 62  
 63             float3 viewDirection = normalize(
 64                _WorldSpaceCameraPos - input.posWorld.xyz);
 65             float3 lightDirection;
 66             float attenuation;
 67  
 68             float4 textureColor = tex2D(_MainTex, input.tex.xy);
 69  
 70             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 71             {
 72                attenuation = 1.0; // no attenuation
 73                lightDirection = 
 74                   normalize(_WorldSpaceLightPos0.xyz);
 75             } 
 76             else // point or spot light
 77             {
 78                float3 vertexToLightSource = 
 79                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 80                float distance = length(vertexToLightSource);
 81                attenuation = 1.0 / distance; // linear attenuation 
 82                lightDirection = normalize(vertexToLightSource);
 83             }
 84  
 85             float3 ambientLighting = textureColor.rgb  
 86                * UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 87  
 88             float3 diffuseReflection = textureColor.rgb  
 89                * attenuation * _LightColor0.rgb * _Color.rgb
 90                * max(0.0, dot(normalDirection, lightDirection));
 91  
 92             float3 specularReflection;
 93             if (dot(normalDirection, lightDirection) < 0.0) 
 94                // light source on the wrong side?
 95             {
 96                specularReflection = float3(0.0, 0.0, 0.0); 
 97                   // no specular reflection
 98             }
 99             else // light source on the right side
100             {
101                specularReflection = attenuation * _LightColor0.rgb 
102                   * _SpecColor.rgb * (1.0 - textureColor.a) 
103                      // for usual gloss maps: "... * textureColor.a" 
104                   * pow(max(0.0, dot(
105                   reflect(-lightDirection, normalDirection), 
106                   viewDirection)), _Shininess);
107             }
108  
109             return float4(ambientLighting + diffuseReflection 
110                + specularReflection, 1.0);
111          }
112  
113          ENDCG
114       }
115  
116       Pass {    
117          Tags { "LightMode" = "ForwardAdd" } 
118             // pass for additional light sources
119          Blend One One // additive blending 
120  
121           CGPROGRAM
122  
123          #pragma vertex vert  
124          #pragma fragment frag 
125  
126          #include "UnityCG.cginc"
127          uniform float4 _LightColor0; 
128             // color of light source (from "Lighting.cginc")
129  
130          // User-specified properties
131          uniform sampler2D _MainTex;    
132          uniform float4 _Color; 
133          uniform float4 _SpecColor; 
134          uniform float _Shininess;
135  
136         struct vertexInput {
137             float4 vertex : POSITION;
138             float3 normal : NORMAL;
139             float4 texcoord : TEXCOORD0;
140         };
141          struct vertexOutput {
142             float4 pos : SV_POSITION;
143             float4 posWorld : TEXCOORD0;
144             float3 normalDir : TEXCOORD1;
145             float4 tex : TEXCOORD2;
146         };
147  
148          vertexOutput vert(vertexInput input) 
149          {
150             vertexOutput output;
151  
152             float4x4 modelMatrix = unity_ObjectToWorld;
153             float4x4 modelMatrixInverse = unity_WorldToObject;
154  
155             output.posWorld = mul(modelMatrix, input.vertex);
156             output.normalDir = normalize(
157                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
158             output.tex = input.texcoord;
159             output.pos = UnityObjectToClipPos(input.vertex);
160             return output;
161          }
162  
163          float4 frag(vertexOutput input) : COLOR
164          {
165             float3 normalDirection = normalize(input.normalDir);
166  
167             float3 viewDirection = normalize(
168                _WorldSpaceCameraPos - input.posWorld.xyz);
169             float3 lightDirection;
170             float attenuation;
171  
172             float4 textureColor = tex2D(_MainTex, input.tex.xy);
173  
174             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
175             {
176                attenuation = 1.0; // no attenuation
177                lightDirection = 
178                   normalize(_WorldSpaceLightPos0.xyz);
179             } 
180             else // point or spot light
181             {
182                float3 vertexToLightSource = 
183                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
184                float distance = length(vertexToLightSource);
185                attenuation = 1.0 / distance; // linear attenuation 
186                lightDirection = normalize(vertexToLightSource);
187             }
188  
189             float3 diffuseReflection = textureColor.rgb  
190                * attenuation * _LightColor0.rgb * _Color.rgb
191                * max(0.0, dot(normalDirection, lightDirection));
192  
193             float3 specularReflection;
194             if (dot(normalDirection, lightDirection) < 0.0) 
195                // light source on the wrong side?
196             {
197                specularReflection = float3(0.0, 0.0, 0.0); 
198                   // no specular reflection
199             }
200             else // light source on the right side
201             {
202                specularReflection = attenuation * _LightColor0.rgb 
203                   * _SpecColor.rgb * (1.0 - textureColor.a) 
204                      // for usual gloss maps: "... * textureColor.a" 
205                   * pow(max(0.0, dot(
206                   reflect(-lightDirection, normalDirection), 
207                   viewDirection)), _Shininess);
208             }
209  
210             return float4(diffuseReflection 
211                + specularReflection, 1.0);
212                // no ambient lighting in this pass
213          }
214  
215          ENDCG
216       }
217    }
218    Fallback "Specular"
219 }
Per-pixel lighting with texture

Transparent Textures (about using alpha textures for discarding fragments, alpha testing, and blending)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg texturing with alpha discard" {
 4    Properties {
 5       _MainTex ("RGBA Texture Image", 2D) = "white" {} 
 6       _Cutoff ("Alpha Cutoff", Float) = 0.5
 7    }
 8    SubShader {
 9       Pass {    
10          Cull Off // since the front is partially transparent, 
11             // we shouldn't cull the back
12 
13          CGPROGRAM
14  
15          #pragma vertex vert  
16          #pragma fragment frag 
17  
18          uniform sampler2D _MainTex;    
19          uniform float _Cutoff;
20  
21          struct vertexInput {
22             float4 vertex : POSITION;
23             float4 texcoord : TEXCOORD0;
24          };
25          struct vertexOutput {
26             float4 pos : SV_POSITION;
27             float4 tex : TEXCOORD0;
28          };
29  
30          vertexOutput vert(vertexInput input) 
31          {
32             vertexOutput output;
33  
34             output.tex = input.texcoord;
35             output.pos = UnityObjectToClipPos(input.vertex);
36             return output;
37          }
38 
39          float4 frag(vertexOutput input) : COLOR
40          {
41             float4 textureColor = tex2D(_MainTex, input.tex.xy);  
42             if (textureColor.a < _Cutoff)
43                // alpha value less than user-specified threshold?
44             {
45                discard; // yes: discard this fragment
46             }
47             return textureColor;
48          }
49  
50          ENDCG
51       }
52    }
53    Fallback "Unlit/Transparent Cutout"
54 }
Texturing with alpha discard
 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/Cg texturing with alpha blending" {
 4    Properties {
 5       _MainTex ("RGBA Texture Image", 2D) = "white" {} 
 6    }
 7    SubShader {
 8       Tags {"Queue" = "Transparent"}
 9 
10       Pass {    
11          Cull Front // first render the back faces
12          ZWrite Off // don't write to depth buffer 
13             // in order not to occlude other objects
14          Blend SrcAlpha OneMinusSrcAlpha 
15             // blend based on the fragment's alpha value
16          
17          CGPROGRAM
18  
19          #pragma vertex vert  
20          #pragma fragment frag 
21  
22          uniform sampler2D _MainTex;
23  
24          struct vertexInput {
25             float4 vertex : POSITION;
26             float4 texcoord : TEXCOORD0;
27          };
28          struct vertexOutput {
29             float4 pos : SV_POSITION;
30             float4 tex : TEXCOORD0;
31          };
32  
33          vertexOutput vert(vertexInput input) 
34          {
35             vertexOutput output;
36  
37             output.tex = input.texcoord;
38             output.pos = UnityObjectToClipPos(input.vertex);
39             return output;
40          }
41 
42          float4 frag(vertexOutput input) : COLOR
43          {
44             return tex2D(_MainTex, input.tex.xy);  
45          }
46  
47          ENDCG
48       }
49 
50       Pass {    
51          Cull Back // now render the front faces
52          ZWrite Off // don't write to depth buffer 
53             // in order not to occlude other objects
54          Blend SrcAlpha OneMinusSrcAlpha 
55             // blend based on the fragment's alpha value
56          
57          CGPROGRAM
58  
59          #pragma vertex vert  
60          #pragma fragment frag 
61  
62          uniform sampler2D _MainTex;
63  
64          struct vertexInput {
65             float4 vertex : POSITION;
66             float4 texcoord : TEXCOORD0;
67          };
68          struct vertexOutput {
69             float4 pos : SV_POSITION;
70             float4 tex : TEXCOORD0;
71          };
72  
73          vertexOutput vert(vertexInput input) 
74          {
75             vertexOutput output;
76  
77             output.tex = input.texcoord;
78             output.pos = UnityObjectToClipPos(input.vertex);
79             return output;
80          }
81 
82          float4 frag(vertexOutput input) : COLOR
83          {
84             return tex2D(_MainTex, input.tex.xy);  
85          }
86  
87          ENDCG
88       }
89    }
90    Fallback "Unlit/Transparent"
91 }
Texturing with alpha blending

  1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  2 
  3 Shader "Custom/Cg semitransparent colors based on alpha" {
  4    Properties {
  5       _MainTex ("RGBA Texture Image", 2D) = "white" {} 
  6    }
  7    SubShader {
  8       Tags {"Queue" = "Transparent"}
  9 
 10       Pass {    
 11          Cull Front // first render the back faces
 12          ZWrite Off // don't write to depth buffer 
 13             // in order not to occlude other objects
 14          Blend SrcAlpha OneMinusSrcAlpha 
 15             // blend based on the fragment's alpha value
 16          
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag 
 21  
 22          uniform sampler2D _MainTex;
 23  
 24          struct vertexInput {
 25             float4 vertex : POSITION;
 26             float4 texcoord : TEXCOORD0;
 27          };
 28          struct vertexOutput {
 29             float4 pos : SV_POSITION;
 30             float4 tex : TEXCOORD0;
 31          };
 32  
 33          vertexOutput vert(vertexInput input) 
 34          {
 35             vertexOutput output;
 36  
 37             output.tex = input.texcoord;
 38             output.pos = UnityObjectToClipPos(input.vertex);
 39             return output;
 40          }
 41 
 42          float4 frag(vertexOutput input) : COLOR
 43          {
 44             float4 color =  tex2D(_MainTex, input.tex.xy);  
 45             if (color.a > 0.5) // opaque back face?
 46             {
 47                color = float4(0.0, 0.0, 0.2, 1.0); 
 48                   // opaque dark blue
 49             }
 50             else // transparent back face?
 51             {
 52                color = float4(0.0, 0.0, 1.0, 0.3); 
 53                   // semitransparent green
 54             }
 55             return color;
 56          }
 57  
 58          ENDCG
 59       }
 60 
 61       Pass {    
 62          Cull Back // now render the front faces
 63          ZWrite Off // don't write to depth buffer 
 64             // in order not to occlude other objects
 65          Blend SrcAlpha OneMinusSrcAlpha 
 66             // blend based on the fragment's alpha value
 67          
 68          CGPROGRAM
 69  
 70          #pragma vertex vert  
 71          #pragma fragment frag 
 72  
 73          uniform sampler2D _MainTex;
 74  
 75          struct vertexInput {
 76             float4 vertex : POSITION;
 77             float4 texcoord : TEXCOORD0;
 78          };
 79          struct vertexOutput {
 80             float4 pos : SV_POSITION;
 81             float4 tex : TEXCOORD0;
 82          };
 83  
 84          vertexOutput vert(vertexInput input) 
 85          {
 86             vertexOutput output;
 87  
 88             output.tex = input.texcoord;
 89             output.pos = UnityObjectToClipPos(input.vertex);
 90             return output;
 91          }
 92 
 93          float4 frag(vertexOutput input) : COLOR
 94          {
 95             float4 color = tex2D(_MainTex, input.tex.xy);  
 96             if (color.a > 0.5) // opaque front face?
 97             {
 98                color = float4(0.0, 1.0, 0.0, 1.0); 
 99                   // opaque green
100             }
101             else // transparent front face
102             {
103                color = float4(0.0, 0.0, 1.0, 0.3); 
104                   // semitransparent dark blue
105             }
106             return color;
107         }
108  
109          ENDCG
110       }
111    }
112    Fallback "Unlit/Transparent"
113 }
Semitransparent colors based on alpha

Layers of Textures (about multitexturing)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg multitexturing of Earth" {
 6    Properties {
 7       _DecalTex ("Daytime Earth", 2D) = "white" {}
 8       _MainTex ("Nighttime Earth", 2D) = "white" {} 
 9       _Color ("Nighttime Color Filter", Color) = (1,1,1,1)
10    }
11    SubShader {
12       Pass {    
13          Tags { "LightMode" = "ForwardBase" } 
14             // pass for the first, directional light 
15  
16          CGPROGRAM
17  
18          #pragma vertex vert  
19          #pragma fragment frag 
20  
21          #include "UnityCG.cginc"
22          uniform float4 _LightColor0; 
23             // color of light source (from "Lighting.cginc")
24  
25          uniform sampler2D _MainTex;
26          uniform sampler2D _DecalTex;
27          uniform float4 _Color; 
28  
29          struct vertexInput {
30             float4 vertex : POSITION;
31             float3 normal : NORMAL;
32             float4 texcoord : TEXCOORD0;
33          };
34          struct vertexOutput {
35             float4 pos : SV_POSITION;
36             float4 tex : TEXCOORD0;
37             float levelOfLighting : TEXCOORD1;
38                // level of diffuse lighting computed in vertex shader
39          };
40  
41          vertexOutput vert(vertexInput input) 
42          {
43             vertexOutput output;
44  
45             float4x4 modelMatrix = unity_ObjectToWorld;
46             float4x4 modelMatrixInverse = unity_WorldToObject;
47  
48             float3 normalDirection = normalize(
49                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
50             float3 lightDirection = normalize(
51                _WorldSpaceLightPos0.xyz);
52  
53             output.levelOfLighting = 
54                max(0.0, dot(normalDirection, lightDirection));
55             output.tex = input.texcoord;
56             output.pos = UnityObjectToClipPos(input.vertex);
57             return output;
58          }
59  
60          float4 frag(vertexOutput input) : COLOR
61          {
62             float4 nighttimeColor = 
63                tex2D(_MainTex, input.tex.xy);    
64             float4 daytimeColor = 
65                tex2D(_DecalTex, input.tex.xy);    
66             return lerp(nighttimeColor, daytimeColor, 
67                input.levelOfLighting);
68                // = daytimeColor * levelOfLighting 
69                // + nighttimeColor * (1.0 - levelOfLighting)
70          }
71  
72          ENDCG
73       }
74    } 
75    Fallback "Decal"
76 }
Multitexturing of Earth

Textures in 3D

Lighting of Bumpy Surfaces (about normal mapping)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg normal mapping" {
  6    Properties {
  7       _BumpMap ("Normal Map", 2D) = "bump" {}
  8       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  9       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
 10       _Shininess ("Shininess", Float) = 10
 11    }
 12 
 13    CGINCLUDE // common code for all passes of all subshaders
 14 
 15       #include "UnityCG.cginc"
 16       uniform float4 _LightColor0; 
 17       // color of light source (from "Lighting.cginc")
 18 
 19       // User-specified properties
 20       uniform sampler2D _BumpMap;   
 21       uniform float4 _BumpMap_ST;
 22       uniform float4 _Color; 
 23       uniform float4 _SpecColor; 
 24       uniform float _Shininess;
 25 
 26       struct vertexInput {
 27          float4 vertex : POSITION;
 28          float4 texcoord : TEXCOORD0;
 29          float3 normal : NORMAL;
 30          float4 tangent : TANGENT;
 31       };
 32       struct vertexOutput {
 33          float4 pos : SV_POSITION;
 34          float4 posWorld : TEXCOORD0;
 35          // position of the vertex (and fragment) in world space 
 36          float4 tex : TEXCOORD1;
 37          float3 tangentWorld : TEXCOORD2;  
 38          float3 normalWorld : TEXCOORD3;
 39          float3 binormalWorld : TEXCOORD4;
 40       };
 41 
 42       vertexOutput vert(vertexInput input) 
 43       {
 44          vertexOutput output;
 45 
 46          float4x4 modelMatrix = unity_ObjectToWorld;
 47          float4x4 modelMatrixInverse = unity_WorldToObject;
 48 
 49          output.tangentWorld = normalize(
 50             mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
 51          output.normalWorld = normalize(
 52             mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 53          output.binormalWorld = normalize(
 54             cross(output.normalWorld, output.tangentWorld) 
 55             * input.tangent.w); // tangent.w is specific to Unity
 56 
 57          output.posWorld = mul(modelMatrix, input.vertex);
 58          output.tex = input.texcoord;
 59          output.pos = UnityObjectToClipPos(input.vertex);
 60          return output;
 61       }
 62 
 63       // fragment shader with ambient lighting
 64       float4 fragWithAmbient(vertexOutput input) : COLOR
 65       {
 66          // in principle we have to normalize tangentWorld,
 67          // binormalWorld, and normalWorld again; however, the 
 68          // potential problems are small since we use this 
 69          // matrix only to compute "normalDirection", 
 70          // which we normalize anyways
 71 
 72          float4 encodedNormal = tex2D(_BumpMap, 
 73             _BumpMap_ST.xy * input.tex.xy + _BumpMap_ST.zw);
 74          float3 localCoords = float3(2.0 * encodedNormal.a - 1.0, 
 75              2.0 * encodedNormal.g - 1.0, 0.0);
 76          localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
 77          // approximation without sqrt:  localCoords.z = 
 78          // 1.0 - 0.5 * dot(localCoords, localCoords);
 79 
 80          float3x3 local2WorldTranspose = float3x3(
 81             input.tangentWorld, 
 82             input.binormalWorld, 
 83             input.normalWorld);
 84          float3 normalDirection = 
 85             normalize(mul(localCoords, local2WorldTranspose));
 86 
 87          float3 viewDirection = normalize(
 88             _WorldSpaceCameraPos - input.posWorld.xyz);
 89          float3 lightDirection;
 90          float attenuation;
 91 
 92          if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 93          { 
 94             attenuation = 1.0; // no attenuation
 95             lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 96          } 
 97          else // point or spot light
 98          {
 99             float3 vertexToLightSource = 
100                _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
101             float distance = length(vertexToLightSource);
102             attenuation = 1.0 / distance; // linear attenuation 
103             lightDirection = normalize(vertexToLightSource);
104          }
105 
106          float3 ambientLighting = 
107             UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
108 
109          float3 diffuseReflection = 
110             attenuation * _LightColor0.rgb * _Color.rgb
111             * max(0.0, dot(normalDirection, lightDirection));
112 
113          float3 specularReflection;
114          if (dot(normalDirection, lightDirection) < 0.0) 
115             // light source on the wrong side?
116          {
117             specularReflection = float3(0.0, 0.0, 0.0); 
118             // no specular reflection
119          }
120          else // light source on the right side
121          {
122             specularReflection = attenuation * _LightColor0.rgb 
123                * _SpecColor.rgb * pow(max(0.0, dot(
124                reflect(-lightDirection, normalDirection), 
125                viewDirection)), _Shininess);
126          }
127          return float4(ambientLighting + diffuseReflection 
128             + specularReflection, 1.0);
129       }
130       
131       // fragment shader for pass 2 without ambient lighting 
132       float4 fragWithoutAmbient(vertexOutput input) : COLOR
133       {
134         // in principle we have to normalize tangentWorld,
135         // binormalWorld, and normalWorld again; however, the  
136         // potential problems are small since we use this 
137         // matrix only to compute "normalDirection", 
138         // which we normalize anyways
139 
140         float4 encodedNormal = tex2D(_BumpMap, 
141            _BumpMap_ST.xy * input.tex.xy + _BumpMap_ST.zw);
142         float3 localCoords = float3(2.0 * encodedNormal.a - 1.0, 
143             2.0 * encodedNormal.g - 1.0, 0.0);
144         localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
145            // approximation without sqrt:  localCoords.z = 
146            // 1.0 - 0.5 * dot(localCoords, localCoords);
147 
148         float3x3 local2WorldTranspose = float3x3(
149            input.tangentWorld,
150            input.binormalWorld, 
151            input.normalWorld);
152         float3 normalDirection = 
153            normalize(mul(localCoords, local2WorldTranspose));
154 
155         float3 viewDirection = normalize(
156            _WorldSpaceCameraPos - input.posWorld.xyz);
157         float3 lightDirection;
158         float attenuation;
159 
160         if (0.0 == _WorldSpaceLightPos0.w) // directional light?
161         {
162            attenuation = 1.0; // no attenuation
163            lightDirection = normalize(_WorldSpaceLightPos0.xyz);
164         } 
165         else // point or spot light
166         {
167            float3 vertexToLightSource = 
168               _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
169            float distance = length(vertexToLightSource);
170            attenuation = 1.0 / distance; // linear attenuation 
171            lightDirection = normalize(vertexToLightSource);
172         }
173 
174         float3 diffuseReflection = 
175            attenuation * _LightColor0.rgb * _Color.rgb
176            * max(0.0, dot(normalDirection, lightDirection));
177 
178         float3 specularReflection;
179         if (dot(normalDirection, lightDirection) < 0.0) 
180            // light source on the wrong side?
181         {
182            specularReflection = float3(0.0, 0.0, 0.0); 
183               // no specular reflection
184         }
185         else // light source on the right side
186         {
187            specularReflection = attenuation * _LightColor0.rgb 
188               * _SpecColor.rgb * pow(max(0.0, dot(
189               reflect(-lightDirection, normalDirection), 
190               viewDirection)), _Shininess);
191         }
192         return float4(diffuseReflection + specularReflection, 1.0);
193       }
194    ENDCG
195 
196    SubShader {
197       Pass {      
198          Tags { "LightMode" = "ForwardBase" } 
199             // pass for ambient light and first light source
200  
201          CGPROGRAM
202             #pragma vertex vert  
203             #pragma fragment fragWithAmbient  
204             // the functions are defined in the CGINCLUDE part
205          ENDCG
206       }
207  
208       Pass {      
209          Tags { "LightMode" = "ForwardAdd" } 
210             // pass for additional light sources
211          Blend One One // additive blending 
212  
213          CGPROGRAM
214             #pragma vertex vert  
215             #pragma fragment fragWithoutAmbient
216             // the functions are defined in the CGINCLUDE part
217          ENDCG
218       }
219    }
220 }
Normal mapping

Projection of Bumpy Surfaces (about parallax mapping)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Cg parallax mapping" {
  6    Properties {
  7       _BumpMap ("Normal Map", 2D) = "bump" {}
  8       _ParallaxMap ("Heightmap (in A)", 2D) = "black" {}
  9       _Parallax ("Max Height", Float) = 0.01
 10       _MaxTexCoordOffset ("Max Texture Coordinate Offset", Float) = 
 11          0.01
 12       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
 13       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
 14       _Shininess ("Shininess", Float) = 10
 15    }
 16    CGINCLUDE // common code for all passes of all subshaders
 17       #include "UnityCG.cginc"
 18       uniform float4 _LightColor0; 
 19          // color of light source (from "Lighting.cginc")
 20  
 21       // User-specified properties
 22       uniform sampler2D _BumpMap; 
 23       uniform float4 _BumpMap_ST;
 24       uniform sampler2D _ParallaxMap; 
 25       uniform float4 _ParallaxMap_ST;
 26       uniform float _Parallax;
 27       uniform float _MaxTexCoordOffset;
 28       uniform float4 _Color; 
 29       uniform float4 _SpecColor; 
 30       uniform float _Shininess;
 31  
 32       struct vertexInput {
 33          float4 vertex : POSITION;
 34          float4 texcoord : TEXCOORD0;
 35          float3 normal : NORMAL;
 36          float4 tangent : TANGENT;
 37       };
 38       struct vertexOutput {
 39          float4 pos : SV_POSITION;
 40          float4 posWorld : TEXCOORD0;
 41             // position of the vertex (and fragment) in world space 
 42          float4 tex : TEXCOORD1;
 43          float3 tangentWorld : TEXCOORD2;  
 44          float3 normalWorld : TEXCOORD3;
 45          float3 binormalWorld : TEXCOORD4;
 46          float3 viewDirWorld : TEXCOORD5; 
 47          float3 viewDirInScaledSurfaceCoords : TEXCOORD6;
 48       };
 49  
 50       vertexOutput vert(vertexInput input) 
 51       {
 52          vertexOutput output;
 53  
 54          float4x4 modelMatrix = unity_ObjectToWorld;
 55          float4x4 modelMatrixInverse = unity_WorldToObject; 
 56  
 57          output.tangentWorld = normalize(
 58             mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
 59          output.normalWorld = normalize(
 60             mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 61          output.binormalWorld = normalize(
 62             cross(output.normalWorld, output.tangentWorld) 
 63             * input.tangent.w); // tangent.w is specific to Unity
 64  
 65  
 66          float3 binormal = cross(input.normal, input.tangent.xyz) 
 67             * input.tangent.w;
 68             // appropriately scaled tangent and binormal 
 69             // to map distances from object space to texture space
 70               
 71             float3 viewDirInObjectCoords = mul(
 72             modelMatrixInverse, float4(_WorldSpaceCameraPos, 1.0)).xyz 
 73             - input.vertex.xyz;
 74          float3x3 localSurface2ScaledObjectT = 
 75             float3x3(input.tangent.xyz, binormal, input.normal); 
 76             // vectors are orthogonal
 77          output.viewDirInScaledSurfaceCoords = 
 78             mul(localSurface2ScaledObjectT, viewDirInObjectCoords); 
 79             // we multiply with the transpose to multiply with 
 80             // the "inverse" (apart from the scaling)
 81  
 82          output.posWorld = mul(modelMatrix, input.vertex);
 83          output.viewDirWorld = normalize(
 84             _WorldSpaceCameraPos - output.posWorld.xyz);
 85          output.tex = input.texcoord;
 86          output.pos = UnityObjectToClipPos(input.vertex);
 87          return output;
 88       }
 89       
 90       // fragment shader with ambient lighting
 91       float4 fragWithAmbient(vertexOutput input) : COLOR
 92       {
 93          // parallax mapping: compute height and 
 94          // find offset in texture coordinates 
 95          // for the intersection of the view ray 
 96          // with the surface at this height
 97          
 98          float height = _Parallax 
 99             * (-0.5 + tex2D(_ParallaxMap, _ParallaxMap_ST.xy 
100             * input.tex.xy + _ParallaxMap_ST.zw).x);
101                
102          float2 texCoordOffsets = 
103             clamp(height * input.viewDirInScaledSurfaceCoords.xy 
104             / input.viewDirInScaledSurfaceCoords.z,
105             -_MaxTexCoordOffset, +_MaxTexCoordOffset); 
106               
107          // normal mapping: lookup and decode normal from bump map
108  
109          // in principle we have to normalize tangentWorld,
110          // binormalWorld, and normalWorld again; however, the  
111          // potential problems are small since we use this 
112          // matrix only to compute "normalDirection", 
113          // which we normalize anyways
114 
115          float4 encodedNormal = tex2D(_BumpMap, 
116             _BumpMap_ST.xy * (input.tex.xy + texCoordOffsets) 
117             + _BumpMap_ST.zw);                             
118          float3 localCoords = float3(2.0 * encodedNormal.a - 1.0, 
119                2.0 * encodedNormal.g - 1.0, 0.0);
120          localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
121             // approximation without sqrt:  localCoords.z = 
122             // 1.0 - 0.5 * dot(localCoords, localCoords);
123  
124          float3x3 local2WorldTranspose = float3x3(
125             input.tangentWorld, 
126             input.binormalWorld, 
127             input.normalWorld);
128          float3 normalDirection = 
129             normalize(mul(localCoords, local2WorldTranspose));
130  
131          float3 lightDirection;
132          float attenuation;
133  
134          if (0.0 == _WorldSpaceLightPos0.w) // directional light?
135          {
136             attenuation = 1.0; // no attenuation
137             lightDirection = normalize(_WorldSpaceLightPos0.xyz);
138          } 
139          else // point or spot light
140          {
141             float3 vertexToLightSource = 
142                _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
143             float distance = length(vertexToLightSource);
144             attenuation = 1.0 / distance; // linear attenuation 
145             lightDirection = normalize(vertexToLightSource);
146          }
147  
148          float3 ambientLighting = 
149             UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
150  
151          float3 diffuseReflection = 
152             attenuation * _LightColor0.rgb * _Color.rgb
153             * max(0.0, dot(normalDirection, lightDirection));
154  
155          float3 specularReflection;
156          if (dot(normalDirection, lightDirection) < 0.0) 
157             // light source on the wrong side?
158          {
159             specularReflection = float3(0.0, 0.0, 0.0); 
160                // no specular reflection
161          }
162          else // light source on the right side
163          {
164             specularReflection = attenuation * _LightColor0.rgb 
165                * _SpecColor.rgb * pow(max(0.0, dot(
166                reflect(-lightDirection, normalDirection), 
167                input.viewDirWorld)), _Shininess);
168          }
169          return float4(ambientLighting + diffuseReflection 
170             + specularReflection, 1.0);
171       }
172 
173       // fragement shader for pass 2 without ambient lighting 
174       float4 fragWithoutAmbient(vertexOutput input) : COLOR
175       {
176          // parallax mapping: compute height and 
177          // find offset in texture coordinates 
178          // for the intersection of the view ray 
179          // with the surface at this height
180          
181          float height = _Parallax 
182             * (-0.5 + tex2D(_ParallaxMap, _ParallaxMap_ST.xy 
183             * input.tex.xy + _ParallaxMap_ST.zw).x);
184                
185          float2 texCoordOffsets = 
186             clamp(height * input.viewDirInScaledSurfaceCoords.xy 
187             / input.viewDirInScaledSurfaceCoords.z,
188             -_MaxTexCoordOffset, +_MaxTexCoordOffset); 
189               
190          // normal mapping: lookup and decode normal from bump map
191  
192          // in principle we have to normalize tangentWorld,
193          // binormalWorld, and normalWorld again; however, the  
194          // potential problems are small since we use this 
195          // matrix only to compute "normalDirection", 
196          // which we normalize anyways
197 
198          float4 encodedNormal = tex2D(_BumpMap, 
199             _BumpMap_ST.xy * (input.tex.xy + texCoordOffsets) 
200             + _BumpMap_ST.zw);                             
201          float3 localCoords = float3(2.0 * encodedNormal.a - 1.0, 
202                2.0 * encodedNormal.g - 1.0, 0.0);
203          localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
204             // approximation without sqrt:  localCoords.z = 
205             // 1.0 - 0.5 * dot(localCoords, localCoords);
206  
207          float3x3 local2WorldTranspose = float3x3(
208             input.tangentWorld, 
209             input.binormalWorld, 
210             input.normalWorld);
211          float3 normalDirection = 
212             normalize(mul(localCoords, local2WorldTranspose));
213  
214          float3 lightDirection;
215          float attenuation;
216  
217          if (0.0 == _WorldSpaceLightPos0.w) // directional light?
218          {
219             attenuation = 1.0; // no attenuation
220             lightDirection = normalize(_WorldSpaceLightPos0.xyz);
221          } 
222          else // point or spot light
223          {
224             float3 vertexToLightSource = 
225                _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
226             float distance = length(vertexToLightSource);
227             attenuation = 1.0 / distance; // linear attenuation 
228             lightDirection = normalize(vertexToLightSource);
229          }
230  
231          float3 diffuseReflection = 
232             attenuation * _LightColor0.rgb * _Color.rgb
233             * max(0.0, dot(normalDirection, lightDirection));
234  
235          float3 specularReflection;
236          if (dot(normalDirection, lightDirection) < 0.0) 
237             // light source on the wrong side?
238          {
239             specularReflection = float3(0.0, 0.0, 0.0); 
240                // no specular reflection
241          }
242          else // light source on the right side
243          {
244             specularReflection = attenuation * _LightColor0.rgb 
245                * _SpecColor.rgb * pow(max(0.0, dot(
246                reflect(-lightDirection, normalDirection), 
247                input.viewDirWorld)), _Shininess);
248          } 
249          return float4(diffuseReflection + specularReflection, 
250             1.0);
251       }
252    ENDCG
253    SubShader {
254       Pass {      
255          Tags { "LightMode" = "ForwardBase" } 
256             // pass for ambient light and first light source
257  
258          CGPROGRAM
259             #pragma vertex vert  
260             #pragma fragment fragWithAmbient
261 
262             // the functions are defined in the CGINCLUDE part
263          ENDCG
264       }
265  
266       Pass {      
267          Tags { "LightMode" = "ForwardAdd" } 
268             // pass for additional light sources
269          Blend One One // additive blending 
270  
271          CGPROGRAM
272             #pragma vertex vert  
273             #pragma fragment fragWithoutAmbient  
274           
275             // the functions are defined in the CGINCLUDE part   
276          ENDCG
277       } 
278    }
279 }
Parallax mapping

Cookies (about projective texture mapping for shaping light)

  1 Shader "Cg per-pixel lighting with cookies" {
  2    Properties {
  3       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  4       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  5       _Shininess ("Shininess", Float) = 10
  6    }
  7    SubShader {
  8       Pass {    
  9          Tags { "LightMode" = "ForwardBase" } // pass for ambient light 
 10             // and first directional light source without cookie
 11  
 12          CGPROGRAM
 13  
 14          #pragma vertex vert  
 15          #pragma fragment frag 
 16  
 17          #include "UnityCG.cginc"
 18          uniform float4 _LightColor0; 
 19             // color of light source (from "Lighting.cginc")
 20  
 21          // User-specified properties
 22          uniform float4 _Color; 
 23          uniform float4 _SpecColor; 
 24          uniform float _Shininess;
 25  
 26          struct vertexInput {
 27             float4 vertex : POSITION;
 28             float3 normal : NORMAL;
 29          };
 30          struct vertexOutput {
 31             float4 pos : SV_POSITION;
 32             float4 posWorld : TEXCOORD0;
 33             float3 normalDir : TEXCOORD1;
 34          };
 35  
 36          vertexOutput vert(vertexInput input) 
 37          {
 38             vertexOutput output;
 39  
 40             float4x4 modelMatrix = _Object2World;
 41             float4x4 modelMatrixInverse = _World2Object; 
 42  
 43             output.posWorld = mul(modelMatrix, input.vertex);
 44             output.normalDir = normalize(
 45                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 46             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
 47             return output;
 48          }
 49  
 50          float4 frag(vertexOutput input) : COLOR
 51          {
 52             float3 normalDirection = normalize(input.normalDir);
 53  
 54             float3 viewDirection = normalize(
 55                _WorldSpaceCameraPos - input.posWorld.xyz);
 56             float3 lightDirection = 
 57                normalize(_WorldSpaceLightPos0.xyz);
 58  
 59             float3 ambientLighting = 
 60                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 61  
 62             float3 diffuseReflection = 
 63                _LightColor0.rgb * _Color.rgb
 64                * max(0.0, dot(normalDirection, lightDirection));
 65  
 66             float3 specularReflection;
 67             if (dot(normalDirection, lightDirection) < 0.0) 
 68                // light source on the wrong side?
 69             {
 70                specularReflection = float3(0.0, 0.0, 0.0); 
 71                   // no specular reflection
 72             }
 73             else // light source on the right side
 74             {
 75                specularReflection = _LightColor0.rgb 
 76                   * _SpecColor.rgb * pow(max(0.0, dot(
 77                   reflect(-lightDirection, normalDirection), 
 78                   viewDirection)), _Shininess);
 79             }
 80  
 81             return float4(ambientLighting + diffuseReflection 
 82                + specularReflection, 1.0);
 83          }
 84  
 85          ENDCG
 86       }
 87 
 88       Pass {    
 89          Tags { "LightMode" = "ForwardAdd" } 
 90             // pass for additional light sources
 91          Blend One One // additive blending 
 92  
 93          CGPROGRAM
 94  
 95          #pragma vertex vert  
 96          #pragma fragment frag 
 97  
 98          #include "UnityCG.cginc"
 99          uniform float4 _LightColor0; 
100             // color of light source (from "Lighting.cginc")
101          uniform float4x4 _LightMatrix0; // transformation 
102             // from world to light space (from Autolight.cginc)
103          uniform sampler2D _LightTexture0; 
104             // cookie alpha texture map (from Autolight.cginc)
105  
106          // User-specified properties
107          uniform float4 _Color; 
108          uniform float4 _SpecColor; 
109          uniform float _Shininess;
110  
111          struct vertexInput {
112             float4 vertex : POSITION;
113             float3 normal : NORMAL;
114          };
115          struct vertexOutput {
116             float4 pos : SV_POSITION;
117             float4 posWorld : TEXCOORD0;
118                // position of the vertex (and fragment) in world space 
119             float4 posLight : TEXCOORD1;
120                // position of the vertex (and fragment) in light space
121             float3 normalDir : TEXCOORD2;
122                // surface normal vector in world space
123          };
124  
125          vertexOutput vert(vertexInput input) 
126          {
127             vertexOutput output;
128  
129             float4x4 modelMatrix = _Object2World;
130             float4x4 modelMatrixInverse = _World2Object;
131 
132             output.posWorld = mul(modelMatrix, input.vertex);
133             output.posLight = mul(_LightMatrix0, output.posWorld);
134             output.normalDir = normalize(
135                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
136             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
137             return output;
138          }
139  
140          float4 frag(vertexOutput input) : COLOR
141          {
142             float3 normalDirection = normalize(input.normalDir);
143  
144             float3 viewDirection = normalize(
145                _WorldSpaceCameraPos - input.posWorld.xyz);
146             float3 lightDirection;
147             float attenuation;
148  
149             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
150             {
151                attenuation = 1.0; // no attenuation
152                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
153             } 
154             else // point or spot light
155             {
156                float3 vertexToLightSource = 
157                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
158                float distance = length(vertexToLightSource);
159                attenuation = 1.0 / distance; // linear attenuation 
160                lightDirection = normalize(vertexToLightSource);
161             }
162  
163             float3 diffuseReflection = 
164                attenuation * _LightColor0.rgb * _Color.rgb
165                * max(0.0, dot(normalDirection, lightDirection));
166  
167             float3 specularReflection;
168             if (dot(normalDirection, lightDirection) < 0.0) 
169                // light source on the wrong side?
170             {
171                specularReflection = float3(0.0, 0.0, 0.0); 
172                   // no specular reflection
173             }
174             else // light source on the right side
175             {
176                specularReflection = attenuation * _LightColor0.rgb 
177                   * _SpecColor.rgb * pow(max(0.0, dot(
178                   reflect(-lightDirection, normalDirection), 
179                   viewDirection)), _Shininess);
180             }
181  
182             float cookieAttenuation = 1.0;
183             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
184             {
185                cookieAttenuation = tex2D(_LightTexture0, 
186                   input.posLight.xy).a;
187             }
188             else if (1.0 != _LightMatrix0[3][3]) 
189                // spotlight (i.e. not a point light)?
190             {
191                cookieAttenuation = tex2D(_LightTexture0, 
192                   input.posLight.xy / input.posLight.w 
193                   + float2(0.5, 0.5)).a;
194             }
195 
196             return float4(cookieAttenuation 
197                * (diffuseReflection + specularReflection), 1.0);
198          }
199  
200          ENDCG
201       }
202    }
203    Fallback "Specular"
204 }
Per-pixel lighting with cookies
  1 Shader "Cg per-pixel lighting with cookies" {
  2    Properties {
  3       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  4       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  5       _Shininess ("Shininess", Float) = 10
  6    }
  7    SubShader {
  8       Pass {    
  9          Tags { "LightMode" = "ForwardBase" } // pass for ambient light 
 10             // and first directional light source without cookie
 11  
 12          CGPROGRAM
 13  
 14          #pragma vertex vert  
 15          #pragma fragment frag 
 16  
 17          #include "UnityCG.cginc"
 18          uniform float4 _LightColor0; 
 19             // color of light source (from "Lighting.cginc")
 20  
 21          // User-specified properties
 22          uniform float4 _Color; 
 23          uniform float4 _SpecColor; 
 24          uniform float _Shininess;
 25  
 26          struct vertexInput {
 27             float4 vertex : POSITION;
 28             float3 normal : NORMAL;
 29          };
 30          struct vertexOutput {
 31             float4 pos : SV_POSITION;
 32             float4 posWorld : TEXCOORD0;
 33             float3 normalDir : TEXCOORD1;
 34          };
 35  
 36          vertexOutput vert(vertexInput input) 
 37          {
 38             vertexOutput output;
 39  
 40             float4x4 modelMatrix = _Object2World;
 41             float4x4 modelMatrixInverse = _World2Object;
 42  
 43             output.posWorld = mul(modelMatrix, input.vertex);
 44             output.normalDir = normalize(
 45                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 46             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
 47             return output;
 48          }
 49  
 50          float4 frag(vertexOutput input) : COLOR
 51          {
 52             float3 normalDirection = normalize(input.normalDir);
 53  
 54             float3 viewDirection = normalize(
 55                _WorldSpaceCameraPos - input.posWorld.xyz);
 56             float3 lightDirection = 
 57                normalize(_WorldSpaceLightPos0.xyz);
 58  
 59             float3 ambientLighting = 
 60                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 61  
 62             float3 diffuseReflection = 
 63                _LightColor0.rgb * _Color.rgb
 64                * max(0.0, dot(normalDirection, lightDirection));
 65  
 66             float3 specularReflection;
 67             if (dot(normalDirection, lightDirection) < 0.0) 
 68                // light source on the wrong side?
 69             {
 70                specularReflection = float3(0.0, 0.0, 0.0); 
 71                   // no specular reflection
 72             }
 73             else // light source on the right side
 74             {
 75                specularReflection = _LightColor0.rgb 
 76                   * _SpecColor.rgb * pow(max(0.0, dot(
 77                   reflect(-lightDirection, normalDirection), 
 78                   viewDirection)), _Shininess);
 79             }
 80  
 81             return float4(ambientLighting + diffuseReflection 
 82                + specularReflection, 1.0);
 83          }
 84  
 85          ENDCG
 86       }
 87 
 88       Pass {    
 89          Tags { "LightMode" = "ForwardAdd" } 
 90             // pass for additional light sources
 91          Blend One One // additive blending 
 92  
 93          CGPROGRAM
 94  
 95          #pragma multi_compile_lightpass
 96  
 97          #pragma vertex vert  
 98          #pragma fragment frag 
 99  
100          #include "UnityCG.cginc"
101          uniform float4 _LightColor0; 
102             // color of light source (from "Lighting.cginc")
103          uniform float4x4 _LightMatrix0; // transformation 
104             // from world to light space (from Autolight.cginc)
105          #if defined (DIRECTIONAL_COOKIE) || defined (SPOT)
106             uniform sampler2D _LightTexture0; 
107                // cookie alpha texture map (from Autolight.cginc)
108          #elif defined (POINT_COOKIE)
109             uniform samplerCUBE _LightTexture0; 
110                // cookie alpha texture map (from Autolight.cginc)
111          #endif
112  
113          // User-specified properties
114          uniform float4 _Color; 
115          uniform float4 _SpecColor; 
116          uniform float _Shininess;
117  
118          struct vertexInput {
119             float4 vertex : POSITION;
120             float3 normal : NORMAL;
121          };
122          struct vertexOutput {
123             float4 pos : SV_POSITION;
124             float4 posWorld : TEXCOORD0;
125                // position of the vertex (and fragment) in world space 
126             float4 posLight : TEXCOORD1;
127                // position of the vertex (and fragment) in light space
128             float3 normalDir : TEXCOORD2;
129                // surface normal vector in world space
130          };
131  
132          vertexOutput vert(vertexInput input) 
133          {
134             vertexOutput output;
135  
136             float4x4 modelMatrix = _Object2World;
137             float4x4 modelMatrixInverse = _World2Object;
138 
139             output.posWorld = mul(modelMatrix, input.vertex);
140             output.posLight = mul(_LightMatrix0, output.posWorld);
141             output.normalDir = normalize(
142                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
143             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
144             return output;
145          }
146  
147          float4 frag(vertexOutput input) : COLOR
148          {
149             float3 normalDirection = normalize(input.normalDir);
150  
151             float3 viewDirection = normalize(
152                _WorldSpaceCameraPos - input.posWorld.xyz);
153             float3 lightDirection;
154             float attenuation = 1.0;
155                // by default no attenuation with distance
156 
157             #if defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)
158                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
159             #elif defined (POINT_NOATT)
160                lightDirection = normalize(
161                   _WorldSpaceLightPos0 - input.posWorld.xyz);
162             #elif defined(POINT)||defined(POINT_COOKIE)||defined(SPOT)
163                float3 vertexToLightSource = 
164                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
165                float distance = length(vertexToLightSource);
166                attenuation = 1.0 / distance; // linear attenuation 
167                lightDirection = normalize(vertexToLightSource);
168             #endif
169  
170             float3 diffuseReflection = 
171                attenuation * _LightColor0.rgb * _Color.rgb
172                * max(0.0, dot(normalDirection, lightDirection));
173  
174             float3 specularReflection;
175             if (dot(normalDirection, lightDirection) < 0.0) 
176                // light source on the wrong side?
177             {
178                specularReflection = float3(0.0, 0.0, 0.0); 
179                   // no specular reflection
180             }
181             else // light source on the right side
182             {
183                specularReflection = attenuation * _LightColor0.rgb 
184                   * _SpecColor.rgb * pow(max(0.0, dot(
185                   reflect(-lightDirection, normalDirection), 
186                   viewDirection)), _Shininess);
187             }
188  
189             float cookieAttenuation = 1.0; 
190                // by default no cookie attenuation
191             #if defined (DIRECTIONAL_COOKIE)
192                cookieAttenuation = tex2D(_LightTexture0, 
193                   input.posLight.xy).a;
194             #elif defined (POINT_COOKIE)
195                cookieAttenuation = texCUBE(_LightTexture0, 
196                   input.posLight.xyz).a;
197             #elif defined (SPOT)
198                cookieAttenuation = tex2D(_LightTexture0, 
199                   input.posLight.xy / input.posLight.w 
200                   + float2(0.5, 0.5)).a;
201             #endif
202 
203             return float4(cookieAttenuation 
204                * (diffuseReflection + specularReflection), 1.0);
205          }
206  
207          ENDCG
208       }
209    }
210    Fallback "Specular"
211 }
Per-pixel lighting with cookies

Projectors (about projective texture mapping for projectors)

 1 Shader "Cg projector shader for adding light" {
 2    Properties {
 3       _ShadowTex ("Projected Image", 2D) = "white" {}
 4    }
 5    SubShader {
 6       Pass {      
 7          Blend One One 
 8             // add color of _ShadowTex to the color in the framebuffer 
 9          ZWrite Off // don't change depths
10          Offset -1, -1 // avoid depth fighting
11 
12          CGPROGRAM
13  
14          #pragma vertex vert  
15          #pragma fragment frag 
16  
17          // User-specified properties
18          uniform sampler2D _ShadowTex; 
19  
20          // Projector-specific uniforms
21          uniform float4x4 _Projector; // transformation matrix 
22             // from object space to projector space 
23  
24           struct vertexInput {
25             float4 vertex : POSITION;
26             float3 normal : NORMAL;
27          };
28          struct vertexOutput {
29             float4 pos : SV_POSITION;
30             float4 posProj : TEXCOORD0;
31                // position in projector space
32          };
33  
34          vertexOutput vert(vertexInput input) 
35          {
36             vertexOutput output;
37  
38             output.posProj = mul(_Projector, input.vertex);
39             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
40             return output;
41          }
42  
43  
44          float4 frag(vertexOutput input) : COLOR
45          {
46             if (input.posProj.w > 0.0) // in front of projector?
47             {
48                return tex2D(_ShadowTex , 
49                   input.posProj.xy / input.posProj.w); 
50                // alternatively: return tex2Dproj(  
51                //    _ShadowTex, input.posProj);
52             }
53             else // behind projector
54             {
55                return float4(0.0, 0.0, 0.0, 0.0);
56             }
57          }
58  
59          ENDCG
60       }
61    }  
62    Fallback "Projector/Light"
63 }
Projector shader for adding light
 1 // Upgrade NOTE: replaced '_Projector' with 'unity_Projector'
 2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 3 
 4 Shader "Cg projector shader for drop shadows" {
 5    Properties {
 6       _ShadowTex ("Projected Image", 2D) = "white" {}
 7    }
 8    SubShader {
 9       Pass {      
10          Blend Zero OneMinusSrcAlpha // attenuate color in framebuffer 
11             // by 1 minus alpha of _ShadowTex 
12          ZWrite Off // don't change depths
13          Offset -1, -1 // avoid depth fighting
14          
15          CGPROGRAM
16  
17          #pragma vertex vert  
18          #pragma fragment frag 
19  
20          // User-specified properties
21          uniform sampler2D _ShadowTex; 
22  
23          // Projector-specific uniforms
24          uniform float4x4 unity_Projector; // transformation matrix 
25             // from object space to projector space 
26  
27           struct vertexInput {
28             float4 vertex : POSITION;
29             float3 normal : NORMAL;
30          };
31          struct vertexOutput {
32             float4 pos : SV_POSITION;
33             float4 posProj : TEXCOORD0;
34                // position in projector space
35          };
36  
37          vertexOutput vert(vertexInput input) 
38          {
39             vertexOutput output;
40  
41             output.posProj = mul(unity_Projector, input.vertex);
42             output.pos = UnityObjectToClipPos(input.vertex);
43             return output;
44          }
45  
46  
47          float4 frag(vertexOutput input) : COLOR
48          {
49             if (input.posProj.w > 0.0) // in front of projector?
50             {
51                return tex2D(_ShadowTex , 
52                   input.posProj.xy / input.posProj.w); 
53                // alternatively: return tex2Dproj(  
54                //    _ShadowTex, input.posProj);
55             }
56             else // behind projector
57             {
58                return float4(0.0, 0.0, 0.0, 0.0);
59             }
60          }
61  
62          ENDCG
63       }
64    }  
65    Fallback "Projector/Light"
66 }
Projector shader for drop shadows

Environment Mapping

Reflecting Surfaces (about reflection mapping)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg shader with reflection map" {
 6     Properties {
 7         _Cube("Reflection Map",Cube) = "" {}
 8     }
 9     SubShader{
10         Pass {
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             #include "UnityCG.cginc"
17 
18             // User-specified uniforms
19             uniform samplerCUBE _Cube;
20 
21             struct vertexInput{
22                 float4 vertex:POSITION;
23                 float3 normal:NORMAL;
24             };
25             struct vertexOutput{
26                 float4 pos:SV_POSITION;
27                 float3 normalDir:TEXCOORD0;
28                 float3 viewDir:TEXCOORD1;
29             };
30 
31             vertexOutput vert(vertexInput input){
32                 vertexOutput output;
33 
34                 float4x4 modelMatrix = unity_ObjectToWorld;
35                 float4x4 modelMatrixInverse = unity_WorldToObject;
36 
37                 output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
38                 output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
39                 output.pos = UnityObjectToClipPos(input.vertex);
40 
41                 return output;
42             }
43 
44             float4 frag(vertexOutput input):COLOR{
45                 float3 reflectionDir = reflect(input.viewDir,normalize(input.normalDir));
46                 return texCUBE(_Cube,reflectionDir);
47             }
48 
49             ENDCG
50         }
51     }
52 }
Shader with reflection map

Curved Glass (about refraction mapping)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg shader with refraction mapping" {
 6     Properties {
 7         _Cube("Reflection Map",Cube) = "" {}
 8     }
 9     SubShader {
10         Pass {
11             CGPROGRAM
12 
13             #pragma vertex vert
14             #pragma fragment frag
15 
16             uniform samplerCUBE _Cube;
17 
18             struct vertexInput{
19                 float4 vertex:POSITION;
20                 float3 normal:NORMAL;
21             };
22             struct vertexOutput{
23                 float4 pos:SV_POSITION;
24                 float3 normalDir:TEXCOORD0;
25                 float3 viewDir:TEXCOORD1;
26             };
27 
28             vertexOutput vert(vertexInput input){
29                 vertexOutput output;
30 
31                 float4x4 modelMatrix = unity_ObjectToWorld;
32                 float4x4 modelMatrixInverse = unity_WorldToObject;
33 
34                 output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
35                 output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
36                 output.pos = UnityObjectToClipPos(input.vertex);
37                 return output;
38             }
39 
40             float4 frag(vertexOutput input):COLOR{
41                 float refractiveIndex = 1.5;
42                 float3 refractedDir = refract(normalize(input.viewDir),normalize(input.normalDir),1.0/refractiveIndex);
43                 return texCUBE(_Cube,refractedDir);
44             }
45 
46             ENDCG
47         }
48     }
49 }
Shader with refraction mapping

Skyboxes (about rendering of environment maps as background)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 3 
 4 Shader "Cg shader for skybox" {
 5     Properties {
 6         _Cube("Environment Map",Cube)=""{}
 7     }
 8     SubShader{
 9         Tags { "Queue" = "Background" }    
10         Pass{
11             ZWrite Off
12             Cull Front
13 
14             CGPROGRAM
15 
16             #pragma vertex vert
17             #pragma fragment frag
18 
19             #include "UnityCG.cginc"
20 
21             // User-specified uniform
22             uniform samplerCUBE _Cube;
23 
24             struct vertexInput{
25                 float4 vertex:POSITION;
26             };
27             struct vertexOutput{
28                 float4 pos:SV_POSITION;
29                 float3 viewDir:TEXCOORD1;
30             };
31 
32             vertexOutput vert(vertexInput input){
33                 vertexOutput output;
34 
35                 float4x4 modelMatrix = unity_ObjectToWorld;
36                 output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
37                 output.pos = UnityObjectToClipPos(input.vertex);
38                 return output;
39             }
40 
41             float4 frag(vertexOutput input):COLOR{
42                 return texCUBE(_Cube,input.viewDir);
43             }
44 
45             ENDCG
46         }
47     }
48 }
Shader for skybox
 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Cg shader for Unity-specific skybox" {
 4     Properties {
 5         _Cube("Environment Map",Cube)="white"{}
 6     }
 7     SubShader {
 8         Tags  {"Queue"="Background"}
 9         Pass{
10             ZWrite Off
11             Cull Off
12 
13             CGPROGRAM
14 
15             #pragma vertex vert
16             #pragma fragment frag
17 
18             // User-specified uniforms
19             samplerCUBE _Cube;
20 
21             struct vertexInput{
22                 float4 vertex:POSITION;
23                 float3 texcoord:TEXCOORD0;
24             };
25             struct vertexOutput{
26                 float4 vertex:SV_POSITION;
27                 float3 texcoord:TEXCOORD0;
28             };
29 
30             vertexOutput vert(vertexInput input){
31                 vertexOutput output;
32                 output.vertex = UnityObjectToClipPos(input.vertex);
33                 output.texcoord = input.texcoord;
34                 return output;
35             }
36 
37             float4 frag(vertexOutput input):COLOR{
38                 return texCUBE(_Cube,input.texcoord);
39             }
40 
41             ENDCG
42         }
43     }
44 }
Shader for Unity-specific skybox

Many Light Sources (about image-based lighting)

 1 Shader "Cg shader with image-based diffuse lighting" {
 2    Properties {
 3       _OriginalCube ("Environment Map", Cube) = "" {}
 4       _Cube ("Diffuse Environment Map", Cube) = "" {}
 5    }
 6    SubShader {
 7       Pass {   
 8          CGPROGRAM
 9  
10          #pragma vertex vert  
11          #pragma fragment frag 
12  
13          #include "UnityCG.cginc"
14 
15          // User-specified uniforms
16          uniform samplerCUBE _Cube;   
17  
18          struct vertexInput {
19             float4 vertex : POSITION;
20             float3 normal : NORMAL;
21          };
22          struct vertexOutput {
23             float4 pos : SV_POSITION;
24             float3 normalDir : TEXCOORD0;
25          };
26  
27          vertexOutput vert(vertexInput input) 
28          {
29             vertexOutput output;
30  
31             float4x4 modelMatrixInverse = _World2Object; 
32                // multiplication with unity_Scale.w is unnecessary 
33                // because we normalize transformed vectors
34  
35             output.normalDir = normalize(
36                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
37             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
38             return output;
39          }
40  
41          float4 frag(vertexOutput input) : COLOR
42          {
43             return texCUBE(_Cube, input.normalDir);
44          }
45  
46          ENDCG
47       }
48    }
49 }
Shader with image-based diffuse lighting

Variations on Lighting

Brushed Metal (about anisotropic specular reflection)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg anisotropic per-pixel lighting" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _AlphaX ("Roughness in Brush Direction", Float) = 1.0
 10       _AlphaY ("Roughness orthogonal to Brush Direction", Float) = 1.0
 11    }
 12    SubShader {
 13       Pass {    
 14          Tags { "LightMode" = "ForwardBase" } 
 15             // pass for ambient light and first light source
 16  
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag 
 21  
 22          #include "UnityCG.cginc"
 23          uniform float4 _LightColor0; 
 24             // color of light source (from "Lighting.cginc")
 25  
 26          // User-specified properties
 27          uniform float4 _Color; 
 28          uniform float4 _SpecColor; 
 29          uniform float _AlphaX;
 30          uniform float _AlphaY;
 31  
 32          struct vertexInput {
 33             float4 vertex : POSITION;
 34             float3 normal : NORMAL;
 35             float4 tangent : TANGENT;
 36          };
 37          struct vertexOutput {
 38             float4 pos : SV_POSITION;
 39             float4 posWorld : TEXCOORD0;
 40                // position of the vertex (and fragment) in world space 
 41             float3 viewDir : TEXCOORD1;
 42                // view direction in world space
 43             float3 normalDir : TEXCOORD2;
 44                // surface normal vector in world space
 45             float3 tangentDir : TEXCOORD3;
 46                // brush direction in world space
 47          };
 48  
 49          vertexOutput vert(vertexInput input) 
 50          {
 51             vertexOutput output;
 52  
 53             float4x4 modelMatrix = unity_ObjectToWorld;
 54             float4x4 modelMatrixInverse = unity_WorldToObject; 
 55  
 56             output.posWorld = mul(modelMatrix, input.vertex);
 57             output.viewDir = normalize(_WorldSpaceCameraPos 
 58                - output.posWorld.xyz);
 59             output.normalDir = normalize(
 60                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 61             output.tangentDir = normalize(
 62                mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
 63             output.pos = UnityObjectToClipPos(input.vertex);
 64             return output;
 65          }
 66  
 67          float4 frag(vertexOutput input) : COLOR
 68          {
 69             float3 lightDirection;
 70             float attenuation;
 71  
 72             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 73             {
 74                attenuation = 1.0; // no attenuation
 75                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 76             } 
 77             else // point or spot light
 78             {
 79                float3 vertexToLightSource = 
 80                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 81                float distance = length(vertexToLightSource);
 82                attenuation = 1.0 / distance; // linear attenuation 
 83                lightDirection = normalize(vertexToLightSource);
 84             }
 85  
 86             float3 halfwayVector = 
 87                normalize(lightDirection + input.viewDir);
 88             float3 binormalDirection = 
 89                cross(input.normalDir, input.tangentDir);
 90             float dotLN = dot(lightDirection, input.normalDir); 
 91                // compute this dot product only once
 92  
 93             float3 ambientLighting = 
 94                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 95  
 96             float3 diffuseReflection = 
 97                attenuation * _LightColor0.rgb * _Color.rgb 
 98                * max(0.0, dotLN);
 99  
100             float3 specularReflection;
101             if (dotLN < 0.0) // light source on the wrong side?
102             {
103                specularReflection = float3(0.0, 0.0, 0.0); 
104                   // no specular reflection
105             }
106             else // light source on the right side
107             {
108                float dotHN = dot(halfwayVector, input.normalDir);
109                float dotVN = dot(input.viewDir, input.normalDir);
110                float dotHTAlphaX = 
111                   dot(halfwayVector, input.tangentDir) / _AlphaX;
112                float dotHBAlphaY = dot(halfwayVector, 
113                   binormalDirection) / _AlphaY;
114  
115                specularReflection = 
116                   attenuation * _LightColor0.rgb * _SpecColor.rgb 
117                   * sqrt(max(0.0, dotLN / dotVN)) 
118                   * exp(-2.0 * (dotHTAlphaX * dotHTAlphaX 
119                   + dotHBAlphaY * dotHBAlphaY) / (1.0 + dotHN));
120             }
121             return float4(ambientLighting + diffuseReflection 
122                + specularReflection, 1.0);
123          }
124          ENDCG
125       }
126  
127       Pass {    
128          Tags { "LightMode" = "ForwardAdd" } 
129             // pass for additional light sources
130          Blend One One // additive blending 
131  
132          CGPROGRAM
133  
134          #pragma vertex vert  
135          #pragma fragment frag 
136  
137          #include "UnityCG.cginc"
138          uniform float4 _LightColor0; 
139             // color of light source (from "Lighting.cginc")
140  
141          // User-specified properties
142          uniform float4 _Color; 
143          uniform float4 _SpecColor; 
144          uniform float _AlphaX;
145          uniform float _AlphaY;
146  
147          struct vertexInput {
148             float4 vertex : POSITION;
149             float3 normal : NORMAL;
150             float4 tangent : TANGENT;
151          };
152          struct vertexOutput {
153             float4 pos : SV_POSITION;
154             float4 posWorld : TEXCOORD0;
155                // position of the vertex (and fragment) in world space 
156             float3 viewDir : TEXCOORD1;
157                // view direction in world space
158             float3 normalDir : TEXCOORD2;
159                // surface normal vector in world space
160             float3 tangentDir : TEXCOORD3;
161                // brush direction in world space
162          };
163  
164          vertexOutput vert(vertexInput input) 
165          {
166             vertexOutput output;
167  
168             float4x4 modelMatrix = unity_ObjectToWorld;
169             float4x4 modelMatrixInverse = unity_WorldToObject;
170  
171             output.posWorld = mul(modelMatrix, input.vertex);
172             output.viewDir = normalize(_WorldSpaceCameraPos 
173                - output.posWorld.xyz);
174             output.normalDir = normalize(
175                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
176             output.tangentDir = normalize(
177                mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
178             output.pos = UnityObjectToClipPos(input.vertex);
179             return output;
180          }
181  
182          float4 frag(vertexOutput input) : COLOR
183          {
184             float3 lightDirection;
185             float attenuation;
186  
187             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
188             {
189                attenuation = 1.0; // no attenuation
190                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
191             } 
192             else // point or spot light
193             {
194                float3 vertexToLightSource = 
195                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
196                float distance = length(vertexToLightSource);
197                attenuation = 1.0 / distance; // linear attenuation 
198                lightDirection = normalize(vertexToLightSource);
199             }
200  
201             float3 halfwayVector = 
202                normalize(lightDirection + input.viewDir);
203             float3 binormalDirection = 
204                cross(input.normalDir, input.tangentDir);
205             float dotLN = dot(lightDirection, input.normalDir); 
206                // compute this dot product only once
207  
208             float3 diffuseReflection = 
209                attenuation * _LightColor0.rgb * _Color.rgb 
210                * max(0.0, dotLN);
211  
212             float3 specularReflection;
213             if (dotLN < 0.0) // light source on the wrong side?
214             {
215                specularReflection = float3(0.0, 0.0, 0.0); 
216                   // no specular reflection
217             }
218             else // light source on the right side
219             {
220                float dotHN = dot(halfwayVector, input.normalDir);
221                float dotVN = dot(input.viewDir, input.normalDir);
222                float dotHTAlphaX = 
223                   dot(halfwayVector, input.tangentDir) / _AlphaX;
224                float dotHBAlphaY = dot(halfwayVector, 
225                   binormalDirection) / _AlphaY;
226  
227                specularReflection = 
228                   attenuation * _LightColor0.rgb * _SpecColor.rgb 
229                   * sqrt(max(0.0, dotLN / dotVN)) 
230                   * exp(-2.0 * (dotHTAlphaX * dotHTAlphaX 
231                   + dotHBAlphaY * dotHBAlphaY) / (1.0 + dotHN));
232             }
233             return float4(diffuseReflection 
234                + specularReflection, 1.0);
235          }
236          ENDCG
237       }
238    }
239    Fallback "Specular"
240 }
Anisotropic per-pixel lighting

Specular Highlights at Silhouettes (about the Fresnel factor for specular reflection)

  1 Shader "Custom/Cg Fresnel highlights" {
  2    Properties {
  3       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  4       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  5       _Shininess ("Shininess", Float) = 10
  6    }
  7    SubShader {
  8       Pass {    
  9          Tags { "LightMode" = "ForwardBase" } 
 10             // pass for ambient light and first light source
 11  
 12          CGPROGRAM
 13  
 14          #pragma vertex vert  
 15          #pragma fragment frag 
 16  
 17          #include "UnityCG.cginc"
 18          uniform float4 _LightColor0; 
 19             // color of light source (from "Lighting.cginc")
 20  
 21          // User-specified properties
 22          uniform float4 _Color; 
 23          uniform float4 _SpecColor; 
 24          uniform float _Shininess;
 25  
 26          struct vertexInput {
 27             float4 vertex : POSITION;
 28             float3 normal : NORMAL;
 29          };
 30          struct vertexOutput {
 31             float4 pos : SV_POSITION;
 32             float4 posWorld : TEXCOORD0;
 33             float3 normalDir : TEXCOORD1;
 34          };
 35  
 36          vertexOutput vert(vertexInput input) 
 37          {
 38             vertexOutput output;
 39  
 40             float4x4 modelMatrix = _Object2World;
 41             float3x3 modelMatrixInverse = _World2Object;
 42  
 43             output.posWorld = mul(modelMatrix, input.vertex);
 44             output.normalDir = normalize(mul(input.normal, modelMatrixInverse));
 45             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
 46             return output;
 47          }
 48  
 49          float4 frag(vertexOutput input) : COLOR
 50          {
 51             float3 normalDirection = normalize(input.normalDir);
 52             float3 viewDirection = normalize(
 53                _WorldSpaceCameraPos - input.posWorld.xyz);
 54             float3 lightDirection;
 55             float attenuation;
 56  
 57             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 58             {
 59                attenuation = 1.0; // no attenuation
 60                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 61             } 
 62             else // point or spot light
 63             {
 64                float3 vertexToLightSource = 
 65                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 66                float distance = length(vertexToLightSource);
 67                attenuation = 1.0 / distance; // linear attenuation 
 68                lightDirection = normalize(vertexToLightSource);
 69             }
 70  
 71             float3 ambientLighting = 
 72                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 73  
 74             float3 diffuseReflection = 
 75                attenuation * _LightColor0.rgb * _Color.rgb
 76                * max(0.0, dot(normalDirection, lightDirection));
 77  
 78             float3 specularReflection;
 79             if (dot(normalDirection, lightDirection) < 0.0) 
 80                // light source on the wrong side?
 81             {
 82                specularReflection = float3(0.0, 0.0, 0.0); 
 83                   // no specular reflection
 84             }
 85             else // light source on the right side
 86             {
 87                float3 halfwayDirection = 
 88                   normalize(lightDirection + viewDirection);
 89                float w = pow(1.0 - max(0.0, 
 90                   dot(halfwayDirection, viewDirection)), 5.0);
 91                specularReflection = attenuation * _LightColor0.rgb 
 92                   * lerp(_SpecColor.rgb, float3(1.0, 1.0, 1.0), w) 
 93                   * pow(max(0.0, dot(
 94                   reflect(-lightDirection, normalDirection), 
 95                   viewDirection)), _Shininess);
 96             }
 97             return float4(ambientLighting 
 98                + diffuseReflection + specularReflection, 1.0);
 99          }
100          ENDCG
101       }
102  
103       Pass {    
104          Tags { "LightMode" = "ForwardAdd" } 
105             // pass for additional light sources
106          Blend One One // additive blending
107 
108          CGPROGRAM
109  
110          #pragma vertex vert  
111          #pragma fragment frag 
112  
113          #include "UnityCG.cginc"
114          uniform float4 _LightColor0; 
115             // color of light source (from "Lighting.cginc")
116  
117          // User-specified properties
118          uniform float4 _Color; 
119          uniform float4 _SpecColor; 
120          uniform float _Shininess;
121  
122          struct vertexInput {
123             float4 vertex : POSITION;
124             float3 normal : NORMAL;
125          };
126          struct vertexOutput {
127             float4 pos : SV_POSITION;
128             float4 posWorld : TEXCOORD0;
129             float3 normalDir : TEXCOORD1;
130          };
131  
132          vertexOutput vert(vertexInput input) 
133          {
134             vertexOutput output;
135  
136             float4x4 modelMatrix = _Object2World;
137             float4x4 modelMatrixInverse = _World2Object;
138  
139             output.posWorld = mul(modelMatrix, input.vertex);
140             output.normalDir = normalize(
141                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
142             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
143             return output;
144          }
145  
146          float4 frag(vertexOutput input) : COLOR
147          {
148             float3 normalDirection = normalize(input.normalDir);
149             float3 viewDirection = normalize(
150                _WorldSpaceCameraPos - input.posWorld.xyz);
151             float3 lightDirection;
152             float attenuation;
153  
154             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
155             {
156                attenuation = 1.0; // no attenuation
157                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
158             } 
159             else // point or spot light
160             {
161                float3 vertexToLightSource = 
162                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
163                float distance = length(vertexToLightSource);
164                attenuation = 1.0 / distance; // linear attenuation 
165                lightDirection = normalize(vertexToLightSource);
166             }
167  
168             float3 diffuseReflection = 
169                attenuation * _LightColor0.rgb * _Color.rgb
170                * max(0.0, dot(normalDirection, lightDirection));
171  
172             float3 specularReflection;
173             if (dot(normalDirection, lightDirection) < 0.0) 
174                // light source on the wrong side?
175             {
176                specularReflection = float3(0.0, 0.0, 0.0); 
177                   // no specular reflection
178             }
179             else // light source on the right side
180             {
181                float3 halfwayDirection = 
182                   normalize(lightDirection + viewDirection);
183                float w = pow(1.0 - max(0.0, 
184                   dot(halfwayDirection, viewDirection)), 5.0);
185                specularReflection = attenuation * _LightColor0.rgb 
186                   * lerp(_SpecColor.rgb, float3(1.0, 1.0, 1.0), w) 
187                   * pow(max(0.0, dot(
188                   reflect(-lightDirection, normalDirection), 
189                   viewDirection)), _Shininess);
190             } 
191             return float4(diffuseReflection 
192                + specularReflection, 1.0);
193          }
194          ENDCG
195       }
196    }
197    Fallback "Specular"
198 }
Fresnel highlights

Diffuse Reflection of Skylight (about hemisphere lighting)

 1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
 2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
 3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 4 
 5 Shader "Custom/Cg per-vertex hemisphere lighting" {
 6    Properties {
 7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
 8       _UpperHemisphereColor ("Upper Hemisphere Color", Color) 
 9          = (1,1,1,1) 
10       _LowerHemisphereColor ("Lower Hemisphere Color", Color) 
11          = (1,1,1,1) 
12       _UpVector ("Up Vector", Vector) = (0,1,0,0) 
13    }
14    SubShader {
15       Pass {      
16          CGPROGRAM
17  
18          #pragma vertex vert  
19          #pragma fragment frag 
20  
21          #include "UnityCG.cginc"
22  
23          // shader properties specified by users
24          uniform float4 _Color; 
25          uniform float4 _UpperHemisphereColor;
26          uniform float4 _LowerHemisphereColor;
27          uniform float4 _UpVector;
28  
29          struct vertexInput {
30             float4 vertex : POSITION;
31             float3 normal : NORMAL;
32          };
33          struct vertexOutput {
34             float4 pos : SV_POSITION;
35             float4 col : COLOR;
36                // the hemisphere lighting computed in the vertex shader
37          };
38  
39          vertexOutput vert(vertexInput input) 
40          {
41             vertexOutput output;
42  
43             float4x4 modelMatrix = unity_ObjectToWorld;
44             float4x4 modelMatrixInverse = unity_WorldToObject; 
45  
46             float3 normalDirection = normalize(
47                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
48             float3 upDirection = normalize(_UpVector);
49  
50             float w = 0.5 * (1.0 + dot(upDirection, normalDirection));
51             output.col = (w * _UpperHemisphereColor 
52                + (1.0 - w) * _LowerHemisphereColor) * _Color;
53  
54             output.pos = UnityObjectToClipPos(input.vertex);
55             return output;
56          }
57  
58          float4 frag(vertexOutput input) : COLOR
59          {
60             return input.col;
61          }
62  
63          ENDCG
64       }
65    } 
66 }
Per-vertex hemisphere lighting

Translucent Surfaces (about diffuse and forward-scattered transmission of backlight)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg translucent surfaces" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _Shininess ("Shininess", Float) = 10
 10       _DiffuseTranslucentColor ("Diffuse Translucent Color", Color) 
 11          = (1,1,1,1) 
 12       _ForwardTranslucentColor ("Forward Translucent Color", Color) 
 13          = (1,1,1,1) 
 14       _Sharpness ("Sharpness", Float) = 10
 15    }
 16    SubShader {
 17       Pass {      
 18          Tags { "LightMode" = "ForwardBase" } 
 19             // pass for ambient light and first light source
 20          Cull Off // show frontfaces and backfaces
 21  
 22          CGPROGRAM
 23  
 24          #pragma vertex vert  
 25          #pragma fragment frag 
 26  
 27          #include "UnityCG.cginc"
 28          uniform float4 _LightColor0; 
 29             // color of light source (from "Lighting.cginc")
 30  
 31          // User-specified properties
 32          uniform float4 _Color; 
 33          uniform float4 _SpecColor; 
 34          uniform float _Shininess;
 35          uniform float4 _DiffuseTranslucentColor; 
 36          uniform float4 _ForwardTranslucentColor; 
 37          uniform float _Sharpness;
 38  
 39          struct vertexInput {
 40             float4 vertex : POSITION;
 41             float3 normal : NORMAL;
 42          };
 43          struct vertexOutput {
 44             float4 pos : SV_POSITION;
 45             float4 posWorld : TEXCOORD0;
 46             float3 normalDir : TEXCOORD1;
 47          };
 48  
 49          vertexOutput vert(vertexInput input) 
 50          {
 51             vertexOutput output;
 52  
 53             float4x4 modelMatrix = unity_ObjectToWorld;
 54             float4x4 modelMatrixInverse = unity_WorldToObject; 
 55  
 56             output.posWorld = mul(modelMatrix, input.vertex);
 57             output.normalDir = normalize(
 58                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 59             output.pos = UnityObjectToClipPos(input.vertex);
 60             return output;
 61          }
 62  
 63          float4 frag(vertexOutput input) : COLOR
 64          {
 65             float3 normalDirection = normalize(input.normalDir);
 66             float3 viewDirection = normalize(
 67                _WorldSpaceCameraPos - input.posWorld.xyz);
 68  
 69             normalDirection = faceforward(normalDirection,
 70                -viewDirection, normalDirection);
 71                // flip normal if dot(-viewDirection, normalDirection)>0
 72  
 73             float3 lightDirection;
 74             float attenuation;
 75  
 76             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 77             {
 78                attenuation = 1.0; // no attenuation
 79                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 80             } 
 81             else // point or spot light
 82             {
 83                float3 vertexToLightSource = 
 84                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 85                float distance = length(vertexToLightSource);
 86                attenuation = 1.0 / distance; // linear attenuation 
 87                lightDirection = normalize(vertexToLightSource);
 88             }
 89  
 90             // Computation of the Phong reflection model:
 91  
 92             float3 ambientLighting = 
 93                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
 94  
 95             float3 diffuseReflection = 
 96                attenuation * _LightColor0.rgb * _Color.rgb
 97                * max(0.0, dot(normalDirection, lightDirection));
 98  
 99             float3 specularReflection;
100             if (dot(normalDirection, lightDirection) < 0.0) 
101                // light source on the wrong side?
102             {
103                specularReflection = float3(0.0, 0.0, 0.0); 
104                   // no specular reflection
105             }
106             else // light source on the right side
107             {
108                specularReflection = attenuation * _LightColor0.rgb 
109                   * _SpecColor.rgb * pow(max(0.0, dot(
110                   reflect(-lightDirection, normalDirection), 
111                   viewDirection)), _Shininess);
112             }
113  
114             // Computation of the translucent illumination:
115  
116             float3 diffuseTranslucency = 
117                attenuation * _LightColor0.rgb 
118                * _DiffuseTranslucentColor.rgb 
119                * max(0.0, dot(lightDirection, -normalDirection));
120  
121             float3 forwardTranslucency;
122             if (dot(normalDirection, lightDirection) > 0.0) 
123                // light source on the wrong side?
124             {
125                forwardTranslucency = float3(0.0, 0.0, 0.0); 
126                   // no forward-scattered translucency
127             }
128             else // light source on the right side
129             {
130                forwardTranslucency = attenuation * _LightColor0.rgb
131                   * _ForwardTranslucentColor.rgb * pow(max(0.0, 
132                   dot(-lightDirection, viewDirection)), _Sharpness);
133             }
134  
135             // Computation of the complete illumination:
136  
137             return float4(ambientLighting 
138                + diffuseReflection + specularReflection 
139                + diffuseTranslucency + forwardTranslucency, 1.0);
140          }
141          ENDCG
142       }
143  
144       Pass {      
145          Tags { "LightMode" = "ForwardAdd" } 
146             // pass for additional light sources
147          Cull Off
148          Blend One One // additive blending 
149  
150          CGPROGRAM
151  
152          #pragma vertex vert  
153          #pragma fragment frag 
154  
155          #include "UnityCG.cginc"
156          uniform float4 _LightColor0; 
157             // color of light source (from "Lighting.cginc")
158  
159          // User-specified properties
160          uniform float4 _Color; 
161          uniform float4 _SpecColor; 
162          uniform float _Shininess;
163          uniform float4 _DiffuseTranslucentColor; 
164          uniform float4 _ForwardTranslucentColor; 
165          uniform float _Sharpness;
166  
167          struct vertexInput {
168             float4 vertex : POSITION;
169             float3 normal : NORMAL;
170          };
171          struct vertexOutput {
172             float4 pos : SV_POSITION;
173             float4 posWorld : TEXCOORD0;
174             float3 normalDir : TEXCOORD1;
175          };
176  
177          vertexOutput vert(vertexInput input) 
178          {
179             vertexOutput output;
180  
181             float4x4 modelMatrix = unity_ObjectToWorld;
182             float4x4 modelMatrixInverse = unity_WorldToObject;
183  
184             output.posWorld = mul(modelMatrix, input.vertex);
185             output.normalDir = normalize(
186                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
187             output.pos = UnityObjectToClipPos(input.vertex);
188             return output;
189          }
190  
191          float4 frag(vertexOutput input) : COLOR
192          {
193             float3 normalDirection = normalize(input.normalDir);
194             float3 viewDirection = normalize(
195                _WorldSpaceCameraPos - input.posWorld.xyz);
196  
197             normalDirection = faceforward(normalDirection,
198                -viewDirection, normalDirection);
199                // flip normal if dot(-viewDirection, normalDirection)>0
200  
201             float3 lightDirection;
202             float attenuation;
203  
204             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
205             {
206                attenuation = 1.0; // no attenuation
207                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
208             } 
209             else // point or spot light
210             {
211                float3 vertexToLightSource = 
212                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
213                float distance = length(vertexToLightSource);
214                attenuation = 1.0 / distance; // linear attenuation 
215                lightDirection = normalize(vertexToLightSource);
216             }
217  
218             // Computation of the Phong reflection model:
219  
220             float3 diffuseReflection = 
221                attenuation * _LightColor0.rgb * _Color.rgb
222                * max(0.0, dot(normalDirection, lightDirection));
223  
224             float3 specularReflection;
225             if (dot(normalDirection, lightDirection) < 0.0) 
226                // light source on the wrong side?
227             {
228                specularReflection = float3(0.0, 0.0, 0.0); 
229                   // no specular reflection
230             }
231             else // light source on the right side
232             {
233                specularReflection = attenuation * _LightColor0.rgb 
234                   * _SpecColor.rgb * pow(max(0.0, dot(
235                   reflect(-lightDirection, normalDirection), 
236                   viewDirection)), _Shininess);
237             }
238  
239             // Computation of the translucent illumination:
240  
241             float3 diffuseTranslucency = 
242                attenuation * _LightColor0.rgb 
243                * _DiffuseTranslucentColor.rgb 
244                * max(0.0, dot(lightDirection, -normalDirection));
245  
246             float3 forwardTranslucency;
247             if (dot(normalDirection, lightDirection) > 0.0) 
248                // light source on the wrong side?
249             {
250                forwardTranslucency = float3(0.0, 0.0, 0.0); 
251                   // no forward-scattered translucency
252             }
253             else // light source on the right side
254             {
255                forwardTranslucency = attenuation * _LightColor0.rgb
256                   * _ForwardTranslucentColor.rgb * pow(max(0.0, 
257                   dot(-lightDirection, viewDirection)), _Sharpness);
258             }
259  
260             // Computation of the complete illumination:
261  
262             return float4(diffuseReflection + specularReflection 
263                + diffuseTranslucency + forwardTranslucency, 1.0);
264          }
265          ENDCG
266       }
267    }
268 }
Translucent surfaces

Translucent Bodies (about diffuse lighting with reduced contrast and transmission of diffuse backlight at silhouettes)

  1 Shader "Custom/Cg translucent bodies" {
  2    Properties {
  3       _Color ("Diffuse Color", Color) = (1,1,1,1) 
  4       _Waxiness ("Waxiness", Range(0,1)) = 0
  5       _SpecColor ("Specular Color", Color) = (1,1,1,1) 
  6       _Shininess ("Shininess", Float) = 10
  7       _TranslucentColor ("Translucent Color", Color) = (0,0,0,1)
  8    }
  9    SubShader {
 10       Pass {      
 11          Tags { "LightMode" = "ForwardBase" } // pass for 
 12             // ambient light and first light source on back faces
 13          Cull Front // render back faces only
 14          Blend One Zero // mark rasterized pixels in framebuffer 
 15             // with alpha = 0 (usually they should have alpha = 1)
 16  
 17          CGPROGRAM
 18  
 19          #pragma vertex vert  
 20          #pragma fragment frag 
 21  
 22          #include "UnityCG.cginc"
 23          uniform float4 _LightColor0; 
 24             // color of light source (from "Lighting.cginc")
 25  
 26          // User-specified properties
 27          uniform float4 _Color; 
 28          uniform float _Waxiness;
 29          uniform float4 _SpecColor; 
 30          uniform float _Shininess;
 31          uniform float4 _TranslucentColor; 
 32  
 33          struct vertexInput {
 34             float4 vertex : POSITION;
 35             float3 normal : NORMAL;
 36          };
 37          struct vertexOutput {
 38             float4 pos : SV_POSITION;
 39             float4 posWorld : TEXCOORD0;
 40             float3 normalDir : TEXCOORD1;
 41          };
 42  
 43          vertexOutput vert(vertexInput input) 
 44          {
 45             vertexOutput output;
 46  
 47             float4x4 modelMatrix = _Object2World;
 48             float4x4 modelMatrixInverse = _World2Object; 
 49  
 50             output.posWorld = mul(modelMatrix, input.vertex);
 51             output.normalDir = normalize(
 52                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 53             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
 54             return output;
 55          }
 56  
 57          float4 frag(vertexOutput input) : COLOR
 58          {
 59             float3 normalDirection = normalize(input.normalDir);
 60  
 61             float3 viewDirection = normalize(
 62                _WorldSpaceCameraPos - input.posWorld.xyz);
 63             float3 lightDirection;
 64             float attenuation;
 65  
 66             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 67             {
 68                attenuation = 1.0; // no attenuation
 69                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 70             } 
 71             else // point or spot light
 72             {
 73                float3 vertexToLightSource = 
 74                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 75                float distance = length(vertexToLightSource);
 76                attenuation = 1.0 / distance; // linear attenuation 
 77                lightDirection = normalize(vertexToLightSource);
 78             }
 79  
 80             float3 ambientLighting = _TranslucentColor.rgb
 81                * UNITY_LIGHTMODEL_AMBIENT.rgb;
 82  
 83             float3 diffuseReflection = _TranslucentColor.rgb
 84                * attenuation * _LightColor0.rgb
 85                * max(0.0, dot(normalDirection, lightDirection));
 86  
 87  
 88             float silhouetteness = 
 89                1.0 - abs(dot(viewDirection, normalDirection));
 90  
 91             return float4(silhouetteness 
 92                * (ambientLighting + diffuseReflection), 0.0);
 93          }
 94  
 95          ENDCG
 96       }
 97  
 98       Pass {      
 99          Tags { "LightMode" = "ForwardAdd" } 
100             // pass for additional light sources on back faces
101          Cull Front // render back faces only
102          Blend One One // additive blending 
103  
104          CGPROGRAM
105  
106          #pragma vertex vert  
107          #pragma fragment frag 
108  
109          #include "UnityCG.cginc"
110          uniform float4 _LightColor0; 
111             // color of light source (from "Lighting.cginc")
112  
113          // User-specified properties
114          uniform float4 _Color; 
115          uniform float _Waxiness;
116          uniform float4 _SpecColor; 
117          uniform float _Shininess;
118          uniform float4 _TranslucentColor; 
119  
120          struct vertexInput {
121             float4 vertex : POSITION;
122             float3 normal : NORMAL;
123          };
124          struct vertexOutput {
125             float4 pos : SV_POSITION;
126             float4 posWorld : TEXCOORD0;
127             float3 normalDir : TEXCOORD1;
128          };
129  
130          vertexOutput vert(vertexInput input) 
131          {
132             vertexOutput output;
133  
134             float4x4 modelMatrix = _Object2World;
135             float4x4 modelMatrixInverse = _World2Object;
136  
137             output.posWorld = mul(modelMatrix, input.vertex);
138             output.normalDir = normalize(
139                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
140             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
141             return output;
142          }
143  
144          float4 frag(vertexOutput input) : COLOR
145          {
146             float3 normalDirection = normalize(input.normalDir);
147  
148             float3 viewDirection = normalize(
149                _WorldSpaceCameraPos - input.posWorld.xyz);
150             float3 lightDirection;
151             float attenuation;
152  
153             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
154             {
155                attenuation = 1.0; // no attenuation
156                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
157             } 
158             else // point or spot light
159             {
160                float3 vertexToLightSource = 
161                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
162                float distance = length(vertexToLightSource);
163                attenuation = 1.0 / distance; // linear attenuation 
164                lightDirection = normalize(vertexToLightSource);
165             }
166  
167             float3 diffuseReflection = _TranslucentColor.rgb
168                * attenuation * _LightColor0.rgb
169                * max(0.0, dot(normalDirection, lightDirection));
170  
171             float silhouetteness = 
172                1.0 - abs(dot(viewDirection, normalDirection));
173  
174             return float4(silhouetteness * diffuseReflection, 0.0);
175          }
176  
177          ENDCG
178       }
179  
180       Pass {    
181          Tags { "LightMode" = "ForwardBase" } // pass for 
182             // setting pixels that were not rasterized to black
183          Cull Back // render front faces only (default behavior)
184          Blend Zero OneMinusDstAlpha // set colors of pixels 
185             // with alpha = 1 to black by multiplying with 1-alpha
186  
187          CGPROGRAM 
188  
189          #pragma vertex vert 
190          #pragma fragment frag
191  
192          float4 vert(float4 vertexPos : POSITION) : SV_POSITION 
193          {
194             return mul(UNITY_MATRIX_MVP, vertexPos);
195          }
196  
197          float4 frag(void) : COLOR 
198          {
199             return float4(0.0, 0.0, 0.0, 0.0); 
200          }
201          ENDCG  
202       }
203  
204       Pass {      
205          Tags { "LightMode" = "ForwardBase" } // pass for 
206             // ambient light and first light source on front faces
207          Cull Back // render front faces only
208          Blend One SrcAlpha // multiply color in framebuffer 
209             // with silhouetteness in fragment's alpha and add colors
210  
211          CGPROGRAM
212  
213          #pragma vertex vert  
214          #pragma fragment frag 
215  
216          #include "UnityCG.cginc"
217          uniform float4 _LightColor0; 
218             // color of light source (from "Lighting.cginc")
219  
220          // User-specified properties
221          uniform float4 _Color; 
222          uniform float _Waxiness;
223          uniform float4 _SpecColor; 
224          uniform float _Shininess;
225          uniform float4 _TranslucentColor; 
226  
227          struct vertexInput {
228             float4 vertex : POSITION;
229             float3 normal : NORMAL;
230          };
231          struct vertexOutput {
232             float4 pos : SV_POSITION;
233             float4 posWorld : TEXCOORD0;
234             float3 normalDir : TEXCOORD1;
235          };
236  
237          vertexOutput vert(vertexInput input) 
238          {
239             vertexOutput output;
240  
241             float4x4 modelMatrix = _Object2World;
242             float4x4 modelMatrixInverse = _World2Object;
243  
244             output.posWorld = mul(modelMatrix, input.vertex);
245             output.normalDir = normalize(
246                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
247             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
248             return output;
249          }
250  
251          float4 frag(vertexOutput input) : COLOR
252          {
253             float3 normalDirection = normalize(input.normalDir);
254  
255             float3 viewDirection = normalize(
256                _WorldSpaceCameraPos - input.posWorld.xyz);
257             float3 lightDirection;
258             float attenuation;
259  
260             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
261             {
262                attenuation = 1.0; // no attenuation
263                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
264             } 
265             else // point or spot light
266             {
267                float3 vertexToLightSource = 
268                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
269                float distance = length(vertexToLightSource);
270                attenuation = 1.0 / distance; // linear attenuation 
271                lightDirection = normalize(vertexToLightSource);
272             }
273  
274             float3 ambientLighting = 
275                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
276  
277             float3 diffuseReflection = 
278                attenuation * _LightColor0.rgb * _Color.rgb
279                * (_Waxiness + (1.0 - _Waxiness) 
280                * max(0.0, dot(normalDirection, lightDirection)));
281  
282             float3 specularReflection;
283             if (dot(normalDirection, lightDirection) < 0.0) 
284                // light source on the wrong side?
285             {
286                specularReflection = float3(0.0, 0.0, 0.0); 
287                   // no specular reflection
288             }
289             else // light source on the right side
290             {
291                specularReflection = attenuation * _LightColor0.rgb 
292                   * _SpecColor.rgb * pow(max(0.0, dot(
293                   reflect(-lightDirection, normalDirection), 
294                   viewDirection)), _Shininess);
295             }
296  
297             float silhouetteness = 
298                1.0 - abs(dot(viewDirection, normalDirection));
299  
300             return float4(ambientLighting + diffuseReflection 
301                + specularReflection, silhouetteness);
302          }
303  
304          ENDCG 
305       }
306  
307       Pass {      
308          Tags { "LightMode" = "ForwardAdd" } 
309             // pass for additional light sources on front faces
310          Cull Back // render front faces only
311          Blend One One // additive blending 
312  
313          CGPROGRAM
314  
315          #pragma vertex vert  
316          #pragma fragment frag 
317  
318          #include "UnityCG.cginc"
319          uniform float4 _LightColor0; 
320             // color of light source (from "Lighting.cginc")
321  
322          // User-specified properties
323          uniform float4 _Color; 
324          uniform float _Waxiness;
325          uniform float4 _SpecColor; 
326          uniform float _Shininess;
327          uniform float4 _TranslucentColor; 
328  
329          struct vertexInput {
330             float4 vertex : POSITION;
331             float3 normal : NORMAL;
332          };
333          struct vertexOutput {
334             float4 pos : SV_POSITION;
335             float4 posWorld : TEXCOORD0;
336             float3 normalDir : TEXCOORD1;
337          };
338  
339          vertexOutput vert(vertexInput input) 
340          {
341             vertexOutput output;
342  
343             float4x4 modelMatrix = _Object2World;
344             float4x4 modelMatrixInverse = _World2Object;
345  
346             output.posWorld = mul(modelMatrix, input.vertex);
347             output.normalDir = normalize(
348                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
349             output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
350             return output;
351          }
352  
353          float4 frag(vertexOutput input) : COLOR
354          {
355             float3 normalDirection = normalize(input.normalDir);
356  
357             float3 viewDirection = normalize(
358                _WorldSpaceCameraPos - input.posWorld.xyz);
359             float3 lightDirection;
360             float attenuation;
361  
362             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
363             {
364                attenuation = 1.0; // no attenuation
365                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
366             } 
367             else // point or spot light
368             {
369                float3 vertexToLightSource = 
370                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
371                float distance = length(vertexToLightSource);
372                attenuation = 1.0 / distance; // linear attenuation 
373                lightDirection = normalize(vertexToLightSource);
374             }
375  
376             float3 diffuseReflection = 
377                attenuation * _LightColor0.rgb * _Color.rgb
378                * (_Waxiness + (1.0 - _Waxiness) 
379                * max(0.0, dot(normalDirection, lightDirection)));
380  
381             float3 specularReflection;
382             if (dot(normalDirection, lightDirection) < 0.0) 
383                // light source on the wrong side?
384             {
385                specularReflection = float3(0.0, 0.0, 0.0); 
386                   // no specular reflection
387             }
388             else // light source on the right side
389             {
390                specularReflection = attenuation * _LightColor0.rgb 
391                   * _SpecColor.rgb * pow(max(0.0, dot(
392                   reflect(-lightDirection, normalDirection), 
393                   viewDirection)), _Shininess);
394             }
395  
396             float silhouetteness = 
397                1.0 - abs(dot(viewDirection, normalDirection));
398  
399             return float4(diffuseReflection 
400                + specularReflection, silhouetteness);
401          }
402  
403          ENDCG 
404       }
405    } 
406    Fallback "Specular"
407 }
Translucent bodies

Soft Shadows of Spheres (about rendering the umbra and penumbra of spheres)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg shadow of sphere" {
  6    Properties {
  7       _Color ("Diffuse Material Color", Color) = (1,1,1,1) 
  8       _SpecColor ("Specular Material Color", Color) = (1,1,1,1) 
  9       _Shininess ("Shininess", Float) = 10
 10       _SpherePosition ("Sphere Position", Vector) = (0,0,0,1)
 11       _SphereRadius ("Sphere Radius", Float) = 1
 12       _LightSourceRadius ("Light Source Radius", Float) = 0.005
 13    }
 14    SubShader {
 15       Pass {      
 16          Tags { "LightMode" = "ForwardBase" } 
 17             // pass for ambient light and first light source
 18  
 19          CGPROGRAM
 20  
 21          #pragma vertex vert  
 22          #pragma fragment frag 
 23  
 24          #pragma target 3.0
 25  
 26          #include "UnityCG.cginc"
 27          uniform float4 _LightColor0; 
 28             // color of light source (from "Lighting.cginc")
 29  
 30          // User-specified properties
 31          uniform float4 _Color; 
 32          uniform float4 _SpecColor; 
 33          uniform float _Shininess;
 34          uniform float4 _SpherePosition; 
 35             // center of shadow-casting sphere in world coordinates
 36          uniform float _SphereRadius; 
 37             // radius of shadow-casting sphere
 38          uniform float _LightSourceRadius; 
 39             // in radians for directional light sources
 40  
 41          struct vertexInput {
 42             float4 vertex : POSITION;
 43             float3 normal : NORMAL;
 44          };
 45          struct vertexOutput {
 46             float4 pos : SV_POSITION;
 47             float4 posWorld : TEXCOORD0;
 48             float3 normalDir : TEXCOORD1;
 49          };
 50  
 51          vertexOutput vert(vertexInput input) 
 52          {
 53             vertexOutput output;
 54  
 55             float4x4 modelMatrix = unity_ObjectToWorld;
 56             float4x4 modelMatrixInverse = unity_WorldToObject;
 57  
 58             output.posWorld = mul(modelMatrix, input.vertex);
 59             output.normalDir = normalize(
 60                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 61             output.pos = UnityObjectToClipPos(input.vertex);
 62             return output;
 63          }
 64  
 65          float4 frag(vertexOutput input) : COLOR
 66          {
 67             float3 normalDirection = normalize(input.normalDir);
 68  
 69             float3 viewDirection = normalize(
 70                _WorldSpaceCameraPos - input.posWorld.xyz);
 71             float3 lightDirection;
 72             float lightDistance;
 73             float attenuation;
 74  
 75             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 76             {
 77                attenuation = 1.0; // no attenuation
 78                lightDirection = 
 79                   normalize(_WorldSpaceLightPos0.xyz);
 80                lightDistance = 1.0;
 81             } 
 82             else // point or spot light
 83             {
 84                lightDirection = 
 85                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 86                lightDistance = length(lightDirection);
 87                attenuation = 1.0 / lightDistance; // linear attenuation
 88                lightDirection = lightDirection / lightDistance;
 89             }
 90  
 91             // computation of level of shadowing w  
 92             float3 sphereDirection = 
 93                _SpherePosition.xyz - input.posWorld.xyz;
 94             float sphereDistance = length(sphereDirection);
 95             sphereDirection = sphereDirection / sphereDistance;
 96             float d = lightDistance 
 97                * (asin(min(1.0, 
 98                length(cross(lightDirection, sphereDirection)))) 
 99                - asin(min(1.0, _SphereRadius / sphereDistance)));
100             float w = smoothstep(-1.0, 1.0, -d / _LightSourceRadius);
101             w = w * smoothstep(0.0, 0.2, 
102                dot(lightDirection, sphereDirection));
103             if (0.0 != _WorldSpaceLightPos0.w) // point light source?
104             {
105                w = w * smoothstep(0.0, _SphereRadius, 
106                   lightDistance - sphereDistance);
107             }
108  
109             float3 ambientLighting = 
110                UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb;
111  
112             float3 diffuseReflection = 
113                attenuation * _LightColor0.rgb * _Color.rgb
114                * max(0.0, dot(normalDirection, lightDirection));
115  
116             float3 specularReflection;
117             if (dot(normalDirection, lightDirection) < 0.0) 
118                // light source on the wrong side?
119             {
120                specularReflection = float3(0.0, 0.0, 0.0); 
121                   // no specular reflection
122             }
123             else // light source on the right side
124             {
125                specularReflection = attenuation * _LightColor0.rgb 
126                   * _SpecColor.rgb * pow(max(0.0, dot(
127                   reflect(-lightDirection, normalDirection), 
128                   viewDirection)), _Shininess);
129             }
130  
131             return float4(ambientLighting 
132                + (1.0 - w) * (diffuseReflection + specularReflection), 
133                1.0);
134          }
135  
136          ENDCG
137       }
138  
139       Pass {      
140          Tags { "LightMode" = "ForwardAdd" } 
141             // pass for additional light sources
142          Blend One One // additive blending 
143  
144          CGPROGRAM
145  
146          #pragma vertex vert  
147          #pragma fragment frag 
148  
149          #pragma target 3.0
150  
151          #include "UnityCG.cginc"
152          uniform float4 _LightColor0; 
153             // color of light source (from "Lighting.cginc")
154  
155          // User-specified properties
156          uniform float4 _Color; 
157          uniform float4 _SpecColor; 
158          uniform float _Shininess;
159          uniform float4 _SpherePosition; 
160             // center of shadow-casting sphere in world coordinates
161          uniform float _SphereRadius; 
162             // radius of shadow-casting sphere
163          uniform float _LightSourceRadius; 
164             // in radians for directional light sources
165  
166          struct vertexInput {
167             float4 vertex : POSITION;
168             float3 normal : NORMAL;
169          };
170          struct vertexOutput {
171             float4 pos : SV_POSITION;
172             float4 posWorld : TEXCOORD0;
173             float3 normalDir : TEXCOORD1;
174          };
175  
176          vertexOutput vert(vertexInput input) 
177          {
178             vertexOutput output;
179  
180             float4x4 modelMatrix = unity_ObjectToWorld;
181             float4x4 modelMatrixInverse = unity_WorldToObject;
182  
183             output.posWorld = mul(modelMatrix, input.vertex);
184             output.normalDir = normalize(
185                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
186             output.pos = UnityObjectToClipPos(input.vertex);
187             return output;
188          }
189  
190          float4 frag(vertexOutput input) : COLOR
191          {
192             float3 normalDirection = normalize(input.normalDir);
193  
194             float3 viewDirection = normalize(
195                _WorldSpaceCameraPos - input.posWorld.xyz);
196             float3 lightDirection;
197             float lightDistance;
198             float attenuation;
199  
200             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
201             {
202                attenuation = 1.0; // no attenuation
203                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
204                lightDistance = 1.0;
205             } 
206             else // point or spot light
207             {
208                lightDirection =
209                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
210                lightDistance = length(lightDirection);
211                attenuation = 1.0 / lightDistance; // linear attenuation
212                lightDirection = lightDirection / lightDistance;
213             }
214  
215             // computation of level of shadowing w  
216             float3 sphereDirection = 
217                _SpherePosition.xyz - input.posWorld.xyz;
218             float sphereDistance = length(sphereDirection);
219             sphereDirection = sphereDirection / sphereDistance;
220             float d = lightDistance 
221                * (asin(min(1.0, 
222                length(cross(lightDirection, sphereDirection)))) 
223                - asin(min(1.0, _SphereRadius / sphereDistance)));
224             float w = smoothstep(-1.0, 1.0, -d / _LightSourceRadius);
225             w = w * smoothstep(0.0, 0.2, 
226                dot(lightDirection, sphereDirection));
227             if (0.0 != _WorldSpaceLightPos0.w) // point light source?
228             {
229                w = w * smoothstep(0.0, _SphereRadius, 
230                   lightDistance - sphereDistance);
231             }
232  
233             float3 diffuseReflection = 
234                attenuation * _LightColor0.rgb * _Color.rgb
235                * max(0.0, dot(normalDirection, lightDirection));
236  
237             float3 specularReflection;
238             if (dot(normalDirection, lightDirection) < 0.0) 
239                // light source on the wrong side?
240             {
241                specularReflection = float3(0.0, 0.0, 0.0); 
242                   // no specular reflection
243             }
244             else // light source on the right side
245             {
246                specularReflection = attenuation * _LightColor0.rgb 
247                   * _SpecColor.rgb * pow(max(0.0, dot(
248                   reflect(-lightDirection, normalDirection), 
249                   viewDirection)), _Shininess);
250             }
251  
252             return float4((1.0 - w) * (diffuseReflection 
253                + specularReflection), 1.0);
254          }
255  
256          ENDCG
257       }
258    } 
259    Fallback "Specular"
260 }
Shadow of sphere

Toon Shading (about non-photorealistic rendering)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg shader for toon shading" {
  6    Properties {
  7       _Color ("Diffuse Color", Color) = (1,1,1,1) 
  8       _UnlitColor ("Unlit Diffuse Color", Color) = (0.5,0.5,0.5,1) 
  9       _DiffuseThreshold ("Threshold for Diffuse Colors", Range(0,1)) 
 10          = 0.1 
 11       _OutlineColor ("Outline Color", Color) = (0,0,0,1)
 12       _LitOutlineThickness ("Lit Outline Thickness", Range(0,1)) = 0.1
 13       _UnlitOutlineThickness ("Unlit Outline Thickness", Range(0,1)) 
 14          = 0.4
 15       _SpecColor ("Specular Color", Color) = (1,1,1,1) 
 16       _Shininess ("Shininess", Float) = 10
 17    }
 18    SubShader {
 19       Pass {      
 20          Tags { "LightMode" = "ForwardBase" } 
 21             // pass for ambient light and first light source
 22  
 23          CGPROGRAM
 24  
 25          #pragma vertex vert  
 26          #pragma fragment frag 
 27  
 28          #include "UnityCG.cginc"
 29          uniform float4 _LightColor0; 
 30             // color of light source (from "Lighting.cginc")
 31  
 32          // User-specified properties
 33          uniform float4 _Color; 
 34          uniform float4 _UnlitColor;
 35          uniform float _DiffuseThreshold;
 36          uniform float4 _OutlineColor;
 37          uniform float _LitOutlineThickness;
 38          uniform float _UnlitOutlineThickness;
 39          uniform float4 _SpecColor; 
 40          uniform float _Shininess;
 41  
 42          struct vertexInput {
 43             float4 vertex : POSITION;
 44             float3 normal : NORMAL;
 45          };
 46          struct vertexOutput {
 47             float4 pos : SV_POSITION;
 48             float4 posWorld : TEXCOORD0;
 49             float3 normalDir : TEXCOORD1;
 50          };
 51  
 52          vertexOutput vert(vertexInput input) 
 53          {
 54             vertexOutput output;
 55  
 56             float4x4 modelMatrix = unity_ObjectToWorld;
 57             float4x4 modelMatrixInverse = unity_WorldToObject; 
 58  
 59             output.posWorld = mul(modelMatrix, input.vertex);
 60             output.normalDir = normalize(
 61                mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
 62             output.pos = UnityObjectToClipPos(input.vertex);
 63             return output;
 64          }
 65  
 66          float4 frag(vertexOutput input) : COLOR
 67          {
 68             float3 normalDirection = normalize(input.normalDir);
 69  
 70             float3 viewDirection = normalize(
 71                _WorldSpaceCameraPos - input.posWorld.xyz);
 72             float3 lightDirection;
 73             float attenuation;
 74  
 75             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
 76             {
 77                attenuation = 1.0; // no attenuation
 78                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
 79             } 
 80             else // point or spot light
 81             {
 82                float3 vertexToLightSource = 
 83                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
 84                float distance = length(vertexToLightSource);
 85                attenuation = 1.0 / distance; // linear attenuation 
 86                lightDirection = normalize(vertexToLightSource);
 87             }
 88   
 89             // default: unlit 
 90             float3 fragmentColor = _UnlitColor.rgb; 
 91  
 92             // low priority: diffuse illumination
 93             if (attenuation 
 94                * max(0.0, dot(normalDirection, lightDirection)) 
 95                >= _DiffuseThreshold)
 96             {
 97                fragmentColor = _LightColor0.rgb * _Color.rgb; 
 98             }
 99  
100             // higher priority: outline
101             if (dot(viewDirection, normalDirection) 
102                < lerp(_UnlitOutlineThickness, _LitOutlineThickness, 
103                max(0.0, dot(normalDirection, lightDirection))))
104             {
105                fragmentColor = _LightColor0.rgb * _OutlineColor.rgb; 
106             }
107  
108             // highest priority: highlights
109             if (dot(normalDirection, lightDirection) > 0.0 
110                // light source on the right side?
111                && attenuation *  pow(max(0.0, dot(
112                reflect(-lightDirection, normalDirection), 
113                viewDirection)), _Shininess) > 0.5) 
114                // more than half highlight intensity? 
115             {
116                fragmentColor = _SpecColor.a 
117                   * _LightColor0.rgb * _SpecColor.rgb
118                   + (1.0 - _SpecColor.a) * fragmentColor;
119             }
120             return float4(fragmentColor, 1.0);
121          }
122          ENDCG
123       }
124  
125       Pass {      
126          Tags { "LightMode" = "ForwardAdd" } 
127             // pass for additional light sources
128          Blend SrcAlpha OneMinusSrcAlpha 
129             // blend specular highlights over framebuffer
130  
131          CGPROGRAM
132  
133          #pragma vertex vert  
134          #pragma fragment frag 
135  
136          #include "UnityCG.cginc"
137          uniform float4 _LightColor0; 
138             // color of light source (from "Lighting.cginc")
139  
140          // User-specified properties
141          uniform float4 _Color; 
142          uniform float4 _UnlitColor;
143          uniform float _DiffuseThreshold;
144          uniform float4 _OutlineColor;
145          uniform float _LitOutlineThickness;
146          uniform float _UnlitOutlineThickness;
147          uniform float4 _SpecColor; 
148          uniform float _Shininess;
149  
150          struct vertexInput {
151             float4 vertex : POSITION;
152             float3 normal : NORMAL;
153          };
154          struct vertexOutput {
155             float4 pos : SV_POSITION;
156             float4 posWorld : TEXCOORD0;
157             float3 normalDir : TEXCOORD1;
158          };
159  
160          vertexOutput vert(vertexInput input) 
161          {
162             vertexOutput output;
163  
164             float4x4 modelMatrix = unity_ObjectToWorld;
165             float4x4 modelMatrixInverse = unity_WorldToObject;
166  
167             output.posWorld = mul(modelMatrix, input.vertex);
168             output.normalDir = normalize(
169                mul(float4(input.normal, 0.0), modelMatrixInverse).rgb);
170             output.pos = UnityObjectToClipPos(input.vertex);
171             return output;
172          }
173  
174          float4 frag(vertexOutput input) : COLOR
175          {
176             float3 normalDirection = normalize(input.normalDir);
177  
178             float3 viewDirection = normalize(
179                _WorldSpaceCameraPos - input.posWorld.rgb);
180             float3 lightDirection;
181             float attenuation;
182  
183             if (0.0 == _WorldSpaceLightPos0.w) // directional light?
184             {
185                attenuation = 1.0; // no attenuation
186                lightDirection = normalize(_WorldSpaceLightPos0.xyz);
187             } 
188             else // point or spot light
189             {
190                float3 vertexToLightSource = 
191                   _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
192                float distance = length(vertexToLightSource);
193                attenuation = 1.0 / distance; // linear attenuation 
194                lightDirection = normalize(vertexToLightSource);
195             }
196  
197             float4 fragmentColor = float4(0.0, 0.0, 0.0, 0.0);
198             if (dot(normalDirection, lightDirection) > 0.0 
199                // light source on the right side?
200                && attenuation *  pow(max(0.0, dot(
201                reflect(-lightDirection, normalDirection), 
202                viewDirection)), _Shininess) > 0.5) 
203                // more than half highlight intensity? 
204             {
205                fragmentColor = 
206                   float4(_LightColor0.rgb, 1.0) * _SpecColor;
207             }
208             return fragmentColor;
209          }
210          ENDCG
211       }
212    } 
213    Fallback "Specular"
214 }
Shader for toon shading

Non-Standard Vertex Transformations

Screen Overlays (about a direct transformation from object space to screen space)

 1 Shader "Custom/Cg shader for screen overlays" {
 2    Properties {
 3       _MainTex ("Texture", Rect) = "white" {}
 4       _Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
 5       _X ("X", Float) = 0.0
 6       _Y ("Y", Float) = 0.0
 7       _Width ("Width", Float) = 128
 8       _Height ("Height", Float) = 128
 9    }
10    SubShader {
11       Tags { "Queue" = "Overlay" } // render after everything else
12  
13       Pass {
14          Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
15          ZTest Always // deactivate depth test
16  
17          CGPROGRAM
18  
19          #pragma vertex vert  
20          #pragma fragment frag
21 
22          #include "UnityCG.cginc" 
23            // defines float4 _ScreenParams with x = width;  
24            // y = height; z = 1 + 1.0/width; w = 1 + 1.0/height
25            // and defines float4 _ProjectionParams 
26            // with x = 1 or x = -1 for flipped projection matrix;
27            // y = near clipping plane; z = far clipping plane; and
28            // w = 1 / far clipping plane
29  
30          // User-specified uniforms
31          uniform sampler2D _MainTex;
32          uniform float4 _Color;
33          uniform float _X;
34          uniform float _Y;
35          uniform float _Width;
36          uniform float _Height;
37  
38          struct vertexInput {
39             float4 vertex : POSITION;
40             float4 texcoord : TEXCOORD0;
41          };
42          struct vertexOutput {
43             float4 pos : SV_POSITION;
44             float4 tex : TEXCOORD0;
45          };
46  
47          vertexOutput vert(vertexInput input) 
48          {
49             vertexOutput output;
50  
51             float2 rasterPosition = float2(
52                _X + _ScreenParams.x / 2.0 
53                + _Width * (input.vertex.x + 0.5),
54                _Y + _ScreenParams.y / 2.0 
55                + _Height * (input.vertex.y + 0.5));
56             output.pos = float4(
57                2.0 * rasterPosition.x / _ScreenParams.x - 1.0,
58                _ProjectionParams.x * (2.0 * rasterPosition.y / _ScreenParams.y - 1.0),
59                _ProjectionParams.y, // near plane is at -1.0 or at 0.0
60                1.0);
61  
62             output.tex = float4(input.vertex.x + 0.5, 
63                input.vertex.y + 0.5, 0.0, 0.0);
64                // for a cube, vertex.x and vertex.y 
65                // are -0.5 or 0.5
66             return output;
67          }
68  
69          float4 frag(vertexOutput input) : COLOR
70          {
71             return _Color * tex2D(_MainTex, input.tex.xy);   
72          }
73  
74          ENDCG
75       }
76    }
77 }
Shader for screen overlays

Billboards (about view-aligned projection of objects)

 1 Shader "Custom/Cg  shader for billboards" {
 2    Properties {
 3       _MainTex ("Texture Image", 2D) = "white" {}
 4       _ScaleX ("Scale X", Float) = 1.0
 5       _ScaleY ("Scale Y", Float) = 1.0
 6    }
 7    SubShader {
 8       Pass {   
 9          CGPROGRAM
10  
11          #pragma vertex vert  
12          #pragma fragment frag
13 
14          // User-specified uniforms            
15          uniform sampler2D _MainTex;        
16          uniform float _ScaleX;
17          uniform float _ScaleY;
18 
19          struct vertexInput {
20             float4 vertex : POSITION;
21             float4 tex : TEXCOORD0;
22          };
23          struct vertexOutput {
24             float4 pos : SV_POSITION;
25             float4 tex : TEXCOORD0;
26          };
27  
28          vertexOutput vert(vertexInput input) 
29          {
30             vertexOutput output;
31 
32             output.pos = mul(UNITY_MATRIX_P, 
33               mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
34               + float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
35               * float4(_ScaleX, _ScaleY, 1.0, 1.0));
36  
37             output.tex = input.tex;
38 
39             return output;
40          }
41  
42          float4 frag(vertexOutput input) : COLOR
43          {
44             return tex2D(_MainTex, float2(input.tex.xy));   
45          }
46  
47          ENDCG
48       }
49    }
50 }
Shader for billboards

Nonlinear Deformations (about vertex blending)

 1 Shader "Custom/Cg shader for vertex blending" {
 2    SubShader {
 3       Pass {   
 4          CGPROGRAM
 5  
 6          #pragma vertex vert  
 7          #pragma fragment frag 
 8  
 9          #include "UnityCG.cginc"
10  
11          // Uniforms set by a script
12          uniform float4x4 _Trafo0; // model transformation of bone0
13          uniform float4x4 _Trafo1; // model transformation of bone1
14  
15          struct vertexInput {
16             float4 vertex : POSITION;
17          };
18          struct vertexOutput {
19             float4 pos : SV_POSITION;
20             float4 col : COLOR;
21          };
22  
23          vertexOutput vert(vertexInput input) 
24          {
25             vertexOutput output;
26  
27             float weight0 = input.vertex.z + 0.5; 
28                // depends on the mesh
29             float4 blendedVertex = 
30                weight0 * mul(_Trafo0, input.vertex) 
31                + (1.0 - weight0) * mul(_Trafo1, input.vertex);
32  
33             output.pos = mul(UNITY_MATRIX_VP, blendedVertex);
34  
35             output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0); 
36                // visualize weight0 as red and weight1 as green
37             return output;
38          }
39  
40          float4 frag(vertexOutput input) : COLOR
41          {
42             return input.col;
43          }
44  
45          ENDCG
46       }
47    }
48 }
Shader for vertex blending

Shadows on Planes (about projecting shadows onto planes)

  1 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
  2 // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
  3 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  4 
  5 Shader "Custom/Cg planar shadow" {
  6    Properties {
  7       _Color ("Object's Color", Color) = (0,1,0,1)
  8       _ShadowColor ("Shadow's Color", Color) = (0,0,0,1)
  9    }
 10    SubShader {
 11       Pass {      
 12          Tags { "LightMode" = "ForwardBase" } // rendering of object
 13  
 14          CGPROGRAM
 15  
 16          #pragma vertex vert 
 17          #pragma fragment frag
 18  
 19          // User-specified properties
 20          uniform float4 _Color; 
 21  
 22          float4 vert(float4 vertexPos : POSITION) : SV_POSITION 
 23          {
 24             return UnityObjectToClipPos(vertexPos);
 25          }
 26  
 27          float4 frag(void) : COLOR
 28          {
 29             return _Color; 
 30          }
 31  
 32          ENDCG 
 33       }
 34  
 35       Pass {   
 36          Tags { "LightMode" = "ForwardBase" } 
 37             // rendering of projected shadow
 38          Offset -1.0, -2.0 
 39             // make sure shadow polygons are on top of shadow receiver
 40  
 41          CGPROGRAM
 42  
 43          #pragma vertex vert 
 44          #pragma fragment frag
 45  
 46          #include "UnityCG.cginc"
 47  
 48          // User-specified uniforms
 49          uniform float4 _ShadowColor;
 50          uniform float4x4 _World2Receiver; // transformation from 
 51             // world coordinates to the coordinate system of the plane
 52  
 53          float4 vert(float4 vertexPos : POSITION) : SV_POSITION
 54          {
 55             float4x4 modelMatrix = unity_ObjectToWorld;
 56             float4x4 modelMatrixInverse = unity_WorldToObject; 
 57             float4x4 viewMatrix = 
 58                mul(UNITY_MATRIX_MV, modelMatrixInverse);
 59  
 60             float4 lightDirection;
 61             if (0.0 != _WorldSpaceLightPos0.w) 
 62             {
 63                // point or spot light
 64                lightDirection = normalize(
 65                   mul(modelMatrix, vertexPos - _WorldSpaceLightPos0));
 66             } 
 67             else 
 68             {
 69                // directional light
 70                lightDirection = -normalize(_WorldSpaceLightPos0); 
 71             }
 72  
 73             float4 vertexInWorldSpace = mul(modelMatrix, vertexPos);
 74             float4 world2ReceiverRow1 = 
 75                float4(_World2Receiver[1][0], _World2Receiver[1][1], 
 76                _World2Receiver[1][2], _World2Receiver[1][3]);
 77             float distanceOfVertex = 
 78                dot(world2ReceiverRow1, vertexInWorldSpace); 
 79                // = (_World2Receiver * vertexInWorldSpace).y 
 80                // = height over plane 
 81             float lengthOfLightDirectionInY = 
 82                dot(world2ReceiverRow1, lightDirection); 
 83                // = (_World2Receiver * lightDirection).y 
 84                // = length in y direction
 85  
 86             if (distanceOfVertex > 0.0 && lengthOfLightDirectionInY < 0.0)
 87             {
 88                lightDirection = lightDirection 
 89                   * (distanceOfVertex / (-lengthOfLightDirectionInY));
 90             }
 91             else
 92             {
 93                lightDirection = float4(0.0, 0.0, 0.0, 0.0); 
 94                   // don't move vertex
 95             }
 96  
 97             return mul(UNITY_MATRIX_VP,  
 98                vertexInWorldSpace + lightDirection);
 99          }
100  
101          float4 frag(void) : COLOR 
102          {
103             return _ShadowColor;
104          }
105  
106          ENDCG 
107       }
108    }
109 }
Planar shadow

Image Effects and Compute Shaders

Minimal Image Effect (about basic image post-processing with fragment shaders)

 1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
 2 
 3 Shader "Custom/tintImageEffectShader"
 4 {
 5    Properties
 6    {
 7       _MainTex ("Source", 2D) = "white" {}
 8       _Color ("Tint", Color) = (1,1,1,1)
 9    }
10    SubShader
11    {
12       Cull Off 
13       ZWrite Off 
14       ZTest Always
15 
16       Pass
17       {
18          CGPROGRAM
19          #pragma vertex vertexShader
20          #pragma fragment fragmentShader
21             
22          #include "UnityCG.cginc"
23 
24          struct vertexInput
25          {
26             float4 vertex : POSITION;
27             float2 texcoord : TEXCOORD0;
28          };
29 
30          struct vertexOutput
31          {
32             float2 texcoord : TEXCOORD0;
33             float4 position : SV_POSITION;
34          };
35 
36          vertexOutput vertexShader(vertexInput i)
37          {
38             vertexOutput o;
39             o.position = UnityObjectToClipPos(i.vertex);
40             o.texcoord = i.texcoord;
41             return o;
42          }
43             
44          sampler2D _MainTex;
45          float4 _MainTex_ST;
46          float4 _Color;
47 
48          float4 fragmentShader(vertexOutput i) : COLOR
49          {
50             float4 color = tex2D(_MainTex, 
51                UnityStereoScreenSpaceUVAdjust(
52                i.texcoord, _MainTex_ST));        
53             return color * _Color;
54          }
55          ENDCG
56       }
57    }
58    Fallback Off
59 }
TintImageEffectShader

Miscellaneous

General Cg Topics

Overview of the Programmable Graphics Pipeline

Vertex Transformations (Modeling, Viewing, Projection, and Viewport Transformations)

Vector and Matrix Operations in Cg (includes references about Cg syntax)

Applying Matrix Transformations to Points, Directions, and Normals in Cg

Rasterization (Interpolation of Per-Fragment Varying Parameters)

Per-Fragment Operations (Stencil Test, Depth Test and Blending, etc.)

Anti-Aliasing Techniques

Phong Reflection Model

原文地址:https://www.cnblogs.com/revoid/p/7890276.html