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 }
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 }
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 }
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 }
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 }
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 }
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
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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.)