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

Basics

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

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg basic shader" {    //defines the name of the shader
SubShader { //unity chooses the subshader that fits the GPU best
Pass { //some shaders require multiple passes
CGPROGRAM //here begins the part in Unity's Cg #pragma vertex vert //this specifies the vert function as the vertex shader
#pragma fragment frag //this specifies the frag function as the fragment shader float4 vert(float4 vertexPos:POSITION) : SV_POSITION { //vertex shader
//this line transforms the vertex input parameter
//vertexPos with the built-in matrix UNITY_MATRIX_MVP
//and return it as a nameless vertex output parameter
return UnityObjectToClipPos(vertexPos); //mul(UNITY_MATRIX_MVP,vertexPos)
} float4 frag():COLOR { //fragment shader
//this fragment shader returns a nameless fragment
//output parameter (with semantic COLOR) that is set to
//opaque red(red = 1,green = 0,blue = 0, alpha = 1)
return float4(1.0,0.0,0.0,1.0);
} ENDCG //here ends the part in Cg
}
}
}

Basic Shader

RGB Cube(about vertex output parameters)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader for RGB Cube"{
SubShader{
Pass{
CGPROGRAM #pragma vertex vert //vert function is the vertex shader
#pragma fragment frag //frag function is the fragment shader //for multiple vertex output parameters an ouput structure is defined
struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:TEXCOORD0;
//nointerpolation float4 col:TEXCOORD0;
}; //vertext shader
vertexOutput vert(float4 vertexPos:POSITION){
vertexOutput output; //we don't need to type 'struct' here output.pos = UnityObjectToClipPos(vertexPos);
output.col = vertexPos+float4(0.5,0.5,0.5,0.0); //here the vertex shader writes output data to the output structure.
//we add 0.5 to the x,y,z coordinates,because the coordinates of the cube are between -0.5 and 0.5
//but we need them between 0.0 and 1.0
return output;
} //fragment shader
float4 frag(vertexOutput input):COLOR {
//here the fragment shader returns the "col" input parameter with semantic TEXCOORD0 as nameless
//output parameter with semantic COLOR
return input.col;
} ENDCG
}
}
}

Shader for RGB Cube

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader for RGB Cube"{
SubShader{
Pass{
CGPROGRAM #pragma vertex vert //vert function is the vertex shader
#pragma fragment frag //frag function is the fragment shader void vert(float4 vertexPos:POSITION,out float4 pos:SV_POSITION,out float4 col:TEXCOORD0){
pos = UnityObjectToClipPos(vertexPos);
col = vertexPos+float4(0.5,0.5,0.5,0.0);
return;
} float4 frag(float4 pos:SV_POSITION,float4 col:TEXCOORD0):COLOR{
return col;
} ENDCG
}
}
}

Shader for RGB Cube

Debugging of shaders(about vertex input parameters)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader with all built-in vertex input parameters" {
SubShader {
Pass{
CGPROGRAM #pragma vertex vert
#pragma fragment frag struct vertexInput{
float4 vertex:POSITION; //position(in object coordinates,i.e. local or model coordinates)
float4 tangent:TANGENT; //vector orthogonal to the surface normal
float3 normal:NORMAL; //surface normal vector(in object coordinates;usually normalized to unit length)
float4 texcoord:TEXCOORD0; //0th set of texture,coordinates(a.k.a "UV";between 0 and 1)
float4 texcoord1:TEXCOORD1; //1st set of tex.coors.
float4 texcoord2:TEXCOORD2; //2nd set of tex.coors.
float4 texcoord3:TEXCOORD3; //3rd set of tex.coors.
fixed4 color:COLOR; //color(usually constant)
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:TEXCOOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output;
output.pos = UnityObjectToClipPos(input.vertex);
//output.col = input.texcoord; //set the output color //other possibilities to play with: //output.col = input.vertex;
//output.col = input.tangent;
//output.col = float4(input.normal,1.0);
//output.col = input.texcoord;
//output.col = input.texcoord1;
//output.col = input.texcoord2;
//output.col = input.texcoord3;
output.col = input.color; return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
}
}
}

Shader with all built-in vertex input parameters

 //struct appdata_base {
// float4 vertex : POSITION;
// float3 normal : NORMAL;
// float4 texcoord : TEXCOORD0;
//};
//struct appdata_tan {
// float4 vertex : POSITION;
// float4 tangent : TANGENT;
// float3 normal : NORMAL;
// float4 texcoord : TEXCOORD0;
//};
//struct appdata_full {
// float4 vertex : POSITION;
// float4 tangent : TANGENT;
// float3 normal : NORMAL;
// float4 texcoord : TEXCOORD0;
// float4 texcoord1 : TEXCOORD1;
// float4 texcoord2 : TEXCOORD2;
// float4 texcoord3 : TEXCOORD3;
// fixed4 color : COLOR;
// // and additional texture coordinates only on XBOX360
//};
//struct appdata_img {
// float4 vertex : POSITION;
// half2 texcoord : TEXCOORD0;
//}; Shader "Custom/Cg shader with all built-in vertex input parameters" {
SubShader {
Pass{
CGPROGRAM #pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:TEXCOOORD0;
}; vertexOutput vert(appdata_full input){
vertexOutput output; output.pos = UnityObjectToClipPos(input.vertex);
output.col = input.texcoord; return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
}
}
}

Shader with all built-in vertex input parameters

Shading in World Space(about uniforms)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shading in world space" {
SubShader{
Pass{
CGPROGRAM #pragma vertex vert
#pragma fragment frag //uniform float4x4 _Object2World;
//automatic definition of a Unity-specific uniform parameter
struct vertexInput{
float4 vertex:POSITION;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 position_in_world_space:TEXCOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output; output.pos = UnityObjectToClipPos(input.vertex);
//transformation of input.vertex from object coordinates to world coordinates;
output.position_in_world_space = mul(unity_ObjectToWorld,input.vertex); return output;
} float4 frag(vertexOutput input):COLOR{
//computes the distance between the fragment position and the origin(the 4th coordinates should always be 1 for points)
float dist = distance(input.position_in_world_space,float4(0.0,0.0,0.0,1.0)); if(dist < ){
return float4(0.0,1.0,0.0,1.0);
} else {
return float4(0.1,0.1,0.1,1.0);
}
} ENDCG
}
}
}

Shading in World Space

 uniform float4 _Time,_SinTime,_CosTime;    //time values
uniform float4 _ProjectionParams; //x = 1 or -1 (-1 if projection is flipped) y = near plane; z = far plane; w = 1/far plane
uniform float4 _ScreenParams; //x = width;y = height; z = 1 + 1/width; w = 1+1/height
uniform float3 _WorldSpaceCameraPos;
uniform float4x4 _Object2World; //model(local)matrix
uniform float4x4 _World2Object; //inverse model matrix
uniform float4 _WorldSpaceLightPos(); //position or direction of light source for forward rendering
uniform float4x4 UNITY_MATRIX_MVP; //model view projection matrix
uniform float4x4 UNITY_MATRIX_MV; //model view matrix
uniform float4x4 UNITY_MATRIX_V; //view matrix
uniform float4x4 UNITY_MATRIX_P; //projection matrix
uniform float4x4 UNITY_MATRIX_VP; //view projection matrix
uniform float4x4 UNITY_MATRIX_T_MV; //transpose of model view matrix
uniform float4x4 UNITY_MATRIX_IT_MV;//transpose of the inverse model view matrix
uniform float4 UNITY_LIGHTMODEL_AMBIENT; //ambient color

More Unity-Specific Uniforms

Transparent Surfaces

Cutaways(about discarding fragments and triangle-face culling)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader using discard" {
SubShader{
Pass{
//turn off triangle culling,alternatives are:
//Cull Back(or nothing):cull only back faces
//Cull Front:cull only front faces
Cull off CGPROGRAM #pragma vertex vert
#pragma fragment frag struct vertexInput{
float4 vertex:POSITION;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 posInObjectCoords:TEXCOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output; output.pos = UnityObjectToClipPos(input.vertex);
output.posInObjectCoords = input.vertex; return output;
} float4 frag(vertexOutput input):COLOR{
if(input.posInObjectCoords.y > 0.0){
//return float4(1.0,0.0,0.0,1.0);
discard; //drop the fragment if y coordinate > 0
}
return float4(0.0,1.0,0.0,1.0); //green
} ENDCG
}
}
}

Shader using discard

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shader with two passes using discard" {
SubShader{
// first pass (is executed before the second pass)
Pass{
Cull Front // cull only front faces CGPROGRAM #pragma vertex vert
#pragma fragment frag struct vertexInput{
float4 vertex:POSITION;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 posInObjectCoords:TEXCOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output; output.pos = UnityObjectToClipPos(input.vertex);
output.posInObjectCoords = input.vertex; return output;
} float4 frag(vertexOutput input):COLOR{
if(input.posInObjectCoords.y > 0.0){
discard;// drop the fragment if y coordinate > 0
}
return float4(1.0,0.0,0.0,1.0); // red
} ENDCG
}
// second pass (is executed after the first pass)
Pass{
Cull Back // cull only back faces CGPROGRAM #pragma vertex vert
#pragma fragment frag struct vertexInput{
float4 vertex:POSITION;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 posInObjectCoords:TEXCOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output; output.pos = UnityObjectToClipPos(input.vertex);
output.posInObjectCoords = input.vertex; return output;
} float4 frag(vertexOutput input):COLOR{
if(input.posInObjectCoords.y > 0.0){
discard; // drop the fragment if y coordinate > 0
}
return float4(0.0,1.0,0.0,1.0); // green
} ENDCG
}
}
}

Shader with two passes using discard

Transparency(about blending)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader using blending" {
SubShader{
Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
Pass{
ZWrite Off // don't write to depth buffer in order not to occlude other objects Blend SrcAlpha OneMinusSrcAlpha // use alpha blending CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexInput:POSITION):SV_POSITION{ return UnityObjectToClipPos(vertexInput);
} float4 frag():COLOR{
// the fourth components(alpha) is important: this is semitransparent green
return float4(0.0,1.0,0.0,0.3);
} ENDCG
}
}
}

Shader using blending

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cg shader using blending" {
Subshader{
// draw after all opaque geometry has been drawn
Tags { "Queue" = "Transparent" }
Pass {
Cull Front // first pass renders only back faces (the "inside")
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos:POSITION):SV_POSITION{
return UnityObjectToClipPos(vertexPos);
} float4 frag():COLOR{
// the fourth component(alpha) is important:this is semitransparent red
return float4(1.0,0.0,0.0,0.3);
} ENDCG
} Pass {
Cull Back // second pass renders only front faces (the "outside")
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos:POSITION):SV_POSITION{
return UnityObjectToClipPos(vertexPos);
} float4 frag():COLOR{
// the fourth component(alpha) is important:this is semitransparent green;
return float4(0.0,1.0,0.0,0.3);
} ENDCG
}
}
}

Shader using blending

Order-Independent Transparency(about order-independent blending)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader using additive blending" {
SubShader{
Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
Pass{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend SrcAlpha One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos:POSITION):SV_POSITION{
return UnityObjectToClipPos(vertexPos);
} float4 frag():COLOR{
return float4(1.0,0.0,0.0,0.2);
} ENDCG
}
}
}

Shader using additive blending

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader using multiplicative blending" {
SubShader {
Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
Pass {
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending for attenuation by the fragment's alpha CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertexPos);
} float4 frag(void) : COLOR
{
return float4(1.0, 0.0, 0.0, 0.2);
} ENDCG
}
}
}

Shader using multiplicative blending

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg Shader using order-independent blending" {
SubShader{
Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
Pass{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend Zero OneMinusSrcAlpha // multiplicative blending for attenuation by fragment's alpha CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos:POSITION):SV_POSITION{
return UnityObjectToClipPos(vertexPos);
} float4 frag():COLOR{
return float4(1.0,0.0,0.0,0.2);
} ENDCG
} Pass{
Cull Off // draw front and back faces
ZWrite Off // don't write to depth buffer in order not to occlude other objects
Blend SrcAlpha One // additive blending to add colors CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos:POSITION):SV_POSITION{
return UnityObjectToClipPos(vertexPos);
} float4 frag():COLOR{
return float4(1.0,0.0,0.0,0.2);
} ENDCG
}
}
}

Shader using order-independent blending

Silhouette Enhancement(about transforming normal vectors)

WikiBooks/Cg Programming-LMLPHP

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg silhouette enhancement" {
Properties {
_Color ("Color", Color) = (, , , 0.5) // user-specified RGBA color including opacity
}
SubShader {
Tags { "Queue" = "Transparent" } // draw after all opaque geometry has been drawn
Pass {
ZWrite Off // don't occlude other objects
Blend SrcAlpha OneMinusSrcAlpha // standard alpha blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" uniform float4 _Color; // define shader property for shaders struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normal : TEXCOORD;
float3 viewDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.normal = normalize(mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.viewDir = normalize(_WorldSpaceCameraPos - mul(modelMatrix, input.vertex).xyz); output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normal);
float3 viewDirection = normalize(input.viewDir); float newOpacity = min(1.0, _Color.a / abs(dot(viewDirection, normalDirection)));
return float4(_Color.rgb, newOpacity);
} ENDCG
}
}
}

Silhouette Enhancement

Basic Lighting

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

WikiBooks/Cg Programming-LMLPHP

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-vertex diffuse lighting" {
Properties {
_Color ("Diffuse Material Color",Color) = (,,,)
} SubShader{
Pass{
Tags { "LightMode" = "ForwardBase" } // make sure that all uniforms are correctly set CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source(from "Lighting.cginc")
uniform float4 _Color; // define shader property for shaders struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:COLOR;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); output.col = float4(diffuseReflection,1.0);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
}
} Fallback "Diffuse"
}

Per-vertex diffuse lighting

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cg per-vertex diffuse lighting" {
Properties {
_Color ("Diffuse Material Color",Color) = (,,,)
}
SubShader {
//Pass for first light source
Pass{
Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; //color of light source (from "Lighting.cginc")
uniform float4 _Color; //define shader property for shader struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:COLOR;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); output.col = float4(diffuseReflection,1.0);
output.pos = UnityObjectToClipPos(input.vertex); return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
} Pass {
// pass for additional light source
Tags { "LightMode" = "ForwardAdd" } // additional blending
Blend One One CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // color of light source (from "Lighting.cginc")
uniform float4 _LightColor0;
// define shader property for shaders
uniform float4 _Color; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
}; struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:COLOR;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
float3 lightDirection = normalize(_WorldSpaceLightPos0.xyz); float3 diffuseReflection = _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); output.col = float4(diffuseReflection,1.0);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
}
} Fallback "Diffuse"
}

Per-vertex diffuse lighting

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-vertex diffuse lighting" {
Properties {
_Color ("Diffuse Material Color",Color) = (,,,)
}
SubShader{
Pass{
// pass for first light source
Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // color of light source(from "Lighting.cginc")
uniform float4 _LightColor0;
// define shader property for shaders
uniform float4 _Color; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:COLOR;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
float3 lightDirection;
float attenuation; if(_WorldSpaceLightPos0.w == 0.0){ // directional light
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
} else { // point or spot light
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - mul(modelMatrix,input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); output.col = float4(diffuseReflection,1.0);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
} Pass {
// pass for addtional light source
Tags { "LightMode" = "ForwardAdd" } Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // color of light source(from "Lighting.cginc")
uniform float4 _LightColor0;
// define shader property for shaders
uniform float4 _Color; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float4 col:COLOR;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
float3 lightDirection;
float attenuation; if(_WorldSpaceLightPos0.w == 0.0){ // directional light
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
} else { // point or spot light
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - mul(modelMatrix,input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance;// linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); output.col = float4(diffuseReflection,1.0);
output.pos = UnityObjectToClipPos(input.vertex); return output;
} float4 frag(vertexOutput input):COLOR{
return input.col;
} ENDCG
}
} Fallback "Diffuse"
}

Per-vertex diffuse lighting

Specular Highlights(about per-vertex lighting)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-vertex lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float3x3 modelMatrixInverse = unity_WorldToObject;
float3 normalDirection = normalize(
mul(input.normal, modelMatrixInverse));
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.col = float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float3x3 modelMatrixInverse = unity_WorldToObject;
float3 normalDirection = normalize(
mul(input.normal, modelMatrixInverse));
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.col = float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient contribution in this pass
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
}
}
Fallback "Specular"
}

Per-vertex lighting

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

WikiBooks/Cg Programming-LMLPHPWikiBooks/Cg Programming-LMLPHP

 Shader "Custom/Cg two-sided per-vertex lighting" {
Properties {
_Color ("Front Material Diffuse Color", Color) = (,,,)
_SpecColor ("Front Material Specular Color", Color) = (,,,)
_Shininess ("Front Material Shininess", Float) =
_BackColor ("Back Material Diffuse Color", Color) = (,,,)
_BackSpecColor ("Back Material Specular Color", Color)
= (,,,)
_BackShininess ("Back Material Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source
Cull Back // render only front faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.col = float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending
Cull Back // render only front faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.col = float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient contribution in this pass
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source
Cull Front// render only back faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(
mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _BackColor.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _BackColor.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _BackSpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _BackShininess);
} output.col = float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending
Cull Front // render only back faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; float3 normalDirection = normalize(
mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _BackColor.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _BackSpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _BackShininess);
} output.col = float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient contribution in this pass
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
} }
Fallback "Specular"
}

Two-sided per-vertex lighting

Smooth Specular Highlights(about per-pixel lighting)

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-pixel lighting" {
Properties {
_Color("Diffuse Material Color",Color) = (,,,)
_SpecColor("Specular Material Color",Color) = (,,,)
_Shininess("Shininess",Float) =
}
SubShader {
// pass for ambient light and first light source
Pass {
Tags { "LihgtMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" uniform float4 _LightColor0; // color of light source(from "Lighting.cginc") // User-specified Properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float4 posWorld:TEXCOORD0;
float3 normalDir:TEXCOORD1;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix,input.vertex);
output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex); return output;
} float4 frag(vertexOutput input):COLOR{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if(_WorldSpaceLightPos0.w == 0.0) { // directional light
attenuation = 1.0; // no attenuation;
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
} else { // point on spot light
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0/distance; // linear attenuation;
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting = UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); float3 specularReflection;
if(dot(normalDirection,lightDirection) < 0.0){ // light source on the wrong side?
// no specular reflection
specularReflection = float3(0.0,0.0,0.0);
} else { // light source on the right side
specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0,dot(reflect(-lightDirection,normalDirection),viewDirection)),_Shininess);
} return float4(ambientLighting + diffuseReflection + specularReflection,1.0);
} ENDCG
}
// pass for additional light source
Pass {
Tags { "LightMode" = "ForwardAdd" } Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0; // color of light source(from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput {
float4 pos:SV_POSITION;
float4 posWorld:TEXCOORD0;
float3 normalDir:TEXCOORD1;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix,input.vertex);
output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if(_WorldSpaceLightPos0.w == 0.0){ // directional light
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
} else { // point or spot light
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection = attenuation * _LightColor0.rgb * _Color.rgb * max(0.0,dot(normalDirection,lightDirection)); float3 specularReflection;
if(dot(normalDirection,lightDirection) < 0.0){ // light source on the wrong side?
// no specular reflection
specularReflection = float3(0.0,0.0,0.0);
} else { // light source on the right side
specularReflection = attenuation * _LightColor0.rgb * _SpecColor.rgb * pow(max(0.0,dot(reflect(-lightDirection,normalDirection),viewDirection)),_Shininess);
}
//no ambient lighting in this pass
return float4(diffuseReflection + specularReflection,1.0);
} ENDCG
}
} Fallback "Diffuse"
}

Per-pixel Lighting

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

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg two-sided per-pixel lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
_BackColor ("Back Material Diffuse Color", Color) = (,,,)
_BackSpecColor ("Back Material Specular Color", Color)
= (,,,)
_BackShininess ("Back Material Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source
Cull Back // render only front faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending
Cull Back // render only front faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient lighting in this pass
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source
Cull Front // render only back faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _BackColor.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _BackColor.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _BackSpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _BackShininess);
} return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending
Cull Front // render only back faces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _BackColor;
uniform float4 _BackSpecColor;
uniform float _BackShininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(-input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _BackColor.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _BackSpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _BackShininess);
} return float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient lighting in this pass
} ENDCG
} }
Fallback "Specular"
}

Two-sided per-pixel lighting

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

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-pixel lighting with vertex lights" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" } // pass for
// 4 vertex lights, ambient light & first pixel light CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
float3 vertexLighting : TEXCOORD2;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex); // Diffuse reflection by four "vertex lights"
output.vertexLighting = float3(0.0, 0.0, 0.0);
#ifdef VERTEXLIGHT_ON
for (int index = ; index < ; index++)
{
float4 lightPosition = float4(unity_4LightPosX0[index],
unity_4LightPosY0[index],
unity_4LightPosZ0[index], 1.0); float3 vertexToLightSource =
lightPosition.xyz - output.posWorld.xyz;
float3 lightDirection = normalize(vertexToLightSource);
float squaredDistance =
dot(vertexToLightSource, vertexToLightSource);
float attenuation = 1.0 / (1.0 +
unity_4LightAtten0[index] * squaredDistance);
float3 diffuseReflection = attenuation
* unity_LightColor[index].rgb * _Color.rgb
* max(0.0, dot(output.normalDir, lightDirection)); output.vertexLighting =
output.vertexLighting + diffuseReflection;
}
#endif
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);
float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(input.vertexLighting + ambientLighting
+ diffuseReflection + specularReflection, 1.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos.xyz - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient lighting in this pass
} ENDCG
} }
Fallback "Specular"
}

Per-pixel lighting with vertex lights

Basic Texturing

Textured Spheres (about texturing a sphere)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg shader with single texture" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
// a 2D texture property that we call "_MainTex", which should
// be labeled "Texture Image" in Unity's user interface.
// By default we use the built-in texture "white"
// (alternatives: "black", "gray" and "bump").
}
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex;
// a uniform variable refering to the property above
// (in fact, this is just a small integer specifying a
// "texture unit", which has the texture image "bound"
// to it; Unity takes care of this). struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
// Unity provides default longitude-latitude-like
// texture coordinates at all vertices of a
// sphere mesh as the input parameter
// "input.texcoord" with semantic "TEXCOORD0".
output.pos = UnityObjectToClipPos(input.vertex);
return output;
}
float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, input.tex.xy);
// look up the color of the texture image specified by
// the uniform "_MainTex" at the position specified by
// "input.tex.x" and "input.tex.y" and return it } ENDCG
}
}
Fallback "Unlit/Texture"
}

Shader with single texture

Lighting Textured Surfaces (about textures for diffuse lighting)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-vertex lighting with texture" {
Properties {
_MainTex ("Texture For Diffuse Material Color", 2D) = "white" {}
_Color ("Overall Diffuse Color Filter", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float3 diffuseColor : TEXCOORD1;
float3 specularColor : TEXCOORD2;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.diffuseColor = ambientLighting + diffuseReflection;
output.specularColor = specularReflection;
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return float4(input.specularColor +
input.diffuseColor * tex2D(_MainTex, input.tex.xy),
1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float3 diffuseColor : TEXCOORD1;
float3 specularColor : TEXCOORD2;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 viewDirection = normalize(_WorldSpaceCameraPos
- mul(modelMatrix, input.vertex).xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource = _WorldSpaceLightPos0.xyz
- mul(modelMatrix, input.vertex).xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} output.diffuseColor = diffuseReflection; // no ambient
output.specularColor = specularReflection;
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return float4(input.specularColor +
input.diffuseColor * tex2D(_MainTex, input.tex.xy),
1.0);
} ENDCG
}
}
Fallback "Specular"
}

Per-vertex lighting with texture

Glossy Textures (about gloss mapping)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-pixel lighting with texture" {
Properties {
_MainTex ("RGBA Texture For Material Color", 2D) = "white" {}
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
float4 tex : TEXCOORD2;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; float4 textureColor = tex2D(_MainTex, input.tex.xy); if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting = textureColor.rgb
* UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection = textureColor.rgb
* attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * (1.0 - textureColor.a)
// for usual gloss maps: "... * textureColor.a"
* pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
float4 tex : TEXCOORD2;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; float4 textureColor = tex2D(_MainTex, input.tex.xy); if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection = textureColor.rgb
* attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * (1.0 - textureColor.a)
// for usual gloss maps: "... * textureColor.a"
* pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(diffuseReflection
+ specularReflection, 1.0);
// no ambient lighting in this pass
} ENDCG
}
}
Fallback "Specular"
}

Per-pixel lighting with texture

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

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg texturing with alpha discard" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Float) = 0.5
}
SubShader {
Pass {
Cull Off // since the front is partially transparent,
// we shouldn't cull the back CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex;
uniform float _Cutoff; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float4 textureColor = tex2D(_MainTex, input.tex.xy);
if (textureColor.a < _Cutoff)
// alpha value less than user-specified threshold?
{
discard; // yes: discard this fragment
}
return textureColor;
} ENDCG
}
}
Fallback "Unlit/Transparent Cutout"
}

Texturing with alpha discard

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg texturing with alpha blending" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
}
SubShader {
Tags {"Queue" = "Transparent"} Pass {
Cull Front // first render the back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, input.tex.xy);
} ENDCG
} Pass {
Cull Back // now render the front faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, input.tex.xy);
} ENDCG
}
}
Fallback "Unlit/Transparent"
}

Texturing with alpha blending

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/Cg semitransparent colors based on alpha" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
}
SubShader {
Tags {"Queue" = "Transparent"} Pass {
Cull Front // first render the back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float4 color = tex2D(_MainTex, input.tex.xy);
if (color.a > 0.5) // opaque back face?
{
color = float4(0.0, 0.0, 0.2, 1.0);
// opaque dark blue
}
else // transparent back face?
{
color = float4(0.0, 0.0, 1.0, 0.3);
// semitransparent green
}
return color;
} ENDCG
} Pass {
Cull Back // now render the front faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform sampler2D _MainTex; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float4 color = tex2D(_MainTex, input.tex.xy);
if (color.a > 0.5) // opaque front face?
{
color = float4(0.0, 1.0, 0.0, 1.0);
// opaque green
}
else // transparent front face
{
color = float4(0.0, 0.0, 1.0, 0.3);
// semitransparent dark blue
}
return color;
} ENDCG
}
}
Fallback "Unlit/Transparent"
}

Semitransparent colors based on alpha

Layers of Textures (about multitexturing)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg multitexturing of Earth" {
Properties {
_DecalTex ("Daytime Earth", 2D) = "white" {}
_MainTex ("Nighttime Earth", 2D) = "white" {}
_Color ("Nighttime Color Filter", Color) = (,,,)
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for the first, directional light CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") uniform sampler2D _MainTex;
uniform sampler2D _DecalTex;
uniform float4 _Color; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
float levelOfLighting : TEXCOORD1;
// level of diffuse lighting computed in vertex shader
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 lightDirection = normalize(
_WorldSpaceLightPos0.xyz); output.levelOfLighting =
max(0.0, dot(normalDirection, lightDirection));
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float4 nighttimeColor =
tex2D(_MainTex, input.tex.xy);
float4 daytimeColor =
tex2D(_DecalTex, input.tex.xy);
return lerp(nighttimeColor, daytimeColor,
input.levelOfLighting);
// = daytimeColor * levelOfLighting
// + nighttimeColor * (1.0 - levelOfLighting)
} ENDCG
}
}
Fallback "Decal"
}

Multitexturing of Earth

Textures in 3D

Lighting of Bumpy Surfaces (about normal mapping)

WikiBooks/Cg Programming-LMLPHP

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg normal mapping" {
Properties {
_BumpMap ("Normal Map", 2D) = "bump" {}
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
} CGINCLUDE // common code for all passes of all subshaders #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _BumpMap;
uniform float4 _BumpMap_ST;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float4 tex : TEXCOORD1;
float3 tangentWorld : TEXCOORD2;
float3 normalWorld : TEXCOORD3;
float3 binormalWorld : TEXCOORD4;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.tangentWorld = normalize(
mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
output.normalWorld = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.binormalWorld = normalize(
cross(output.normalWorld, output.tangentWorld)
* input.tangent.w); // tangent.w is specific to Unity output.posWorld = mul(modelMatrix, input.vertex);
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} // fragment shader with ambient lighting
float4 fragWithAmbient(vertexOutput input) : COLOR
{
// in principle we have to normalize tangentWorld,
// binormalWorld, and normalWorld again; however, the
// potential problems are small since we use this
// matrix only to compute "normalDirection",
// which we normalize anyways float4 encodedNormal = tex2D(_BumpMap,
_BumpMap_ST.xy * input.tex.xy + _BumpMap_ST.zw);
float3 localCoords = float3(2.0 * encodedNormal.a - 1.0,
2.0 * encodedNormal.g - 1.0, 0.0);
localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
// approximation without sqrt: localCoords.z =
// 1.0 - 0.5 * dot(localCoords, localCoords); float3x3 local2WorldTranspose = float3x3(
input.tangentWorld,
input.binormalWorld,
input.normalWorld);
float3 normalDirection =
normalize(mul(localCoords, local2WorldTranspose)); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
}
return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} // fragment shader for pass 2 without ambient lighting
float4 fragWithoutAmbient(vertexOutput input) : COLOR
{
// in principle we have to normalize tangentWorld,
// binormalWorld, and normalWorld again; however, the
// potential problems are small since we use this
// matrix only to compute "normalDirection",
// which we normalize anyways float4 encodedNormal = tex2D(_BumpMap,
_BumpMap_ST.xy * input.tex.xy + _BumpMap_ST.zw);
float3 localCoords = float3(2.0 * encodedNormal.a - 1.0,
2.0 * encodedNormal.g - 1.0, 0.0);
localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
// approximation without sqrt: localCoords.z =
// 1.0 - 0.5 * dot(localCoords, localCoords); float3x3 local2WorldTranspose = float3x3(
input.tangentWorld,
input.binormalWorld,
input.normalWorld);
float3 normalDirection =
normalize(mul(localCoords, local2WorldTranspose)); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
}
return float4(diffuseReflection + specularReflection, 1.0);
}
ENDCG SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM
#pragma vertex vert
#pragma fragment fragWithAmbient
// the functions are defined in the CGINCLUDE part
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM
#pragma vertex vert
#pragma fragment fragWithoutAmbient
// the functions are defined in the CGINCLUDE part
ENDCG
}
}
}

Normal mapping

Projection of Bumpy Surfaces (about parallax mapping)

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cg parallax mapping" {
Properties {
_BumpMap ("Normal Map", 2D) = "bump" {}
_ParallaxMap ("Heightmap (in A)", 2D) = "black" {}
_Parallax ("Max Height", Float) = 0.01
_MaxTexCoordOffset ("Max Texture Coordinate Offset", Float) =
0.01
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
CGINCLUDE // common code for all passes of all subshaders
#include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform sampler2D _BumpMap;
uniform float4 _BumpMap_ST;
uniform sampler2D _ParallaxMap;
uniform float4 _ParallaxMap_ST;
uniform float _Parallax;
uniform float _MaxTexCoordOffset;
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float4 tex : TEXCOORD1;
float3 tangentWorld : TEXCOORD2;
float3 normalWorld : TEXCOORD3;
float3 binormalWorld : TEXCOORD4;
float3 viewDirWorld : TEXCOORD5;
float3 viewDirInScaledSurfaceCoords : TEXCOORD6;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.tangentWorld = normalize(
mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
output.normalWorld = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.binormalWorld = normalize(
cross(output.normalWorld, output.tangentWorld)
* input.tangent.w); // tangent.w is specific to Unity float3 binormal = cross(input.normal, input.tangent.xyz)
* input.tangent.w;
// appropriately scaled tangent and binormal
// to map distances from object space to texture space float3 viewDirInObjectCoords = mul(
modelMatrixInverse, float4(_WorldSpaceCameraPos, 1.0)).xyz
- input.vertex.xyz;
float3x3 localSurface2ScaledObjectT =
float3x3(input.tangent.xyz, binormal, input.normal);
// vectors are orthogonal
output.viewDirInScaledSurfaceCoords =
mul(localSurface2ScaledObjectT, viewDirInObjectCoords);
// we multiply with the transpose to multiply with
// the "inverse" (apart from the scaling) output.posWorld = mul(modelMatrix, input.vertex);
output.viewDirWorld = normalize(
_WorldSpaceCameraPos - output.posWorld.xyz);
output.tex = input.texcoord;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} // fragment shader with ambient lighting
float4 fragWithAmbient(vertexOutput input) : COLOR
{
// parallax mapping: compute height and
// find offset in texture coordinates
// for the intersection of the view ray
// with the surface at this height float height = _Parallax
* (-0.5 + tex2D(_ParallaxMap, _ParallaxMap_ST.xy
* input.tex.xy + _ParallaxMap_ST.zw).x); float2 texCoordOffsets =
clamp(height * input.viewDirInScaledSurfaceCoords.xy
/ input.viewDirInScaledSurfaceCoords.z,
-_MaxTexCoordOffset, +_MaxTexCoordOffset); // normal mapping: lookup and decode normal from bump map // in principle we have to normalize tangentWorld,
// binormalWorld, and normalWorld again; however, the
// potential problems are small since we use this
// matrix only to compute "normalDirection",
// which we normalize anyways float4 encodedNormal = tex2D(_BumpMap,
_BumpMap_ST.xy * (input.tex.xy + texCoordOffsets)
+ _BumpMap_ST.zw);
float3 localCoords = float3(2.0 * encodedNormal.a - 1.0,
2.0 * encodedNormal.g - 1.0, 0.0);
localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
// approximation without sqrt: localCoords.z =
// 1.0 - 0.5 * dot(localCoords, localCoords); float3x3 local2WorldTranspose = float3x3(
input.tangentWorld,
input.binormalWorld,
input.normalWorld);
float3 normalDirection =
normalize(mul(localCoords, local2WorldTranspose)); float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
input.viewDirWorld)), _Shininess);
}
return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} // fragement shader for pass 2 without ambient lighting
float4 fragWithoutAmbient(vertexOutput input) : COLOR
{
// parallax mapping: compute height and
// find offset in texture coordinates
// for the intersection of the view ray
// with the surface at this height float height = _Parallax
* (-0.5 + tex2D(_ParallaxMap, _ParallaxMap_ST.xy
* input.tex.xy + _ParallaxMap_ST.zw).x); float2 texCoordOffsets =
clamp(height * input.viewDirInScaledSurfaceCoords.xy
/ input.viewDirInScaledSurfaceCoords.z,
-_MaxTexCoordOffset, +_MaxTexCoordOffset); // normal mapping: lookup and decode normal from bump map // in principle we have to normalize tangentWorld,
// binormalWorld, and normalWorld again; however, the
// potential problems are small since we use this
// matrix only to compute "normalDirection",
// which we normalize anyways float4 encodedNormal = tex2D(_BumpMap,
_BumpMap_ST.xy * (input.tex.xy + texCoordOffsets)
+ _BumpMap_ST.zw);
float3 localCoords = float3(2.0 * encodedNormal.a - 1.0,
2.0 * encodedNormal.g - 1.0, 0.0);
localCoords.z = sqrt(1.0 - dot(localCoords, localCoords));
// approximation without sqrt: localCoords.z =
// 1.0 - 0.5 * dot(localCoords, localCoords); float3x3 local2WorldTranspose = float3x3(
input.tangentWorld,
input.binormalWorld,
input.normalWorld);
float3 normalDirection =
normalize(mul(localCoords, local2WorldTranspose)); float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
input.viewDirWorld)), _Shininess);
}
return float4(diffuseReflection + specularReflection,
1.0);
}
ENDCG
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM
#pragma vertex vert
#pragma fragment fragWithAmbient // the functions are defined in the CGINCLUDE part
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM
#pragma vertex vert
#pragma fragment fragWithoutAmbient // the functions are defined in the CGINCLUDE part
ENDCG
}
}
}

Parallax mapping

Cookies (about projective texture mapping for shaping light)

WikiBooks/Cg Programming-LMLPHP

 Shader "Cg per-pixel lighting with cookies" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" } // pass for ambient light
// and first directional light source without cookie CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection =
normalize(_WorldSpaceLightPos0.xyz); float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
_LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")
uniform float4x4 _LightMatrix0; // transformation
// from world to light space (from Autolight.cginc)
uniform sampler2D _LightTexture0;
// cookie alpha texture map (from Autolight.cginc) // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float4 posLight : TEXCOORD1;
// position of the vertex (and fragment) in light space
float3 normalDir : TEXCOORD2;
// surface normal vector in world space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.posLight = mul(_LightMatrix0, output.posWorld);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} float cookieAttenuation = 1.0;
if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
cookieAttenuation = tex2D(_LightTexture0,
input.posLight.xy).a;
}
else if (1.0 != _LightMatrix0[][])
// spotlight (i.e. not a point light)?
{
cookieAttenuation = tex2D(_LightTexture0,
input.posLight.xy / input.posLight.w
+ float2(0.5, 0.5)).a;
} return float4(cookieAttenuation
* (diffuseReflection + specularReflection), 1.0);
} ENDCG
}
}
Fallback "Specular"
}

Per-pixel lighting with cookies

 Shader "Cg per-pixel lighting with cookies" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" } // pass for ambient light
// and first directional light source without cookie CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection =
normalize(_WorldSpaceLightPos0.xyz); float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
_LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma multi_compile_lightpass #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc")
uniform float4x4 _LightMatrix0; // transformation
// from world to light space (from Autolight.cginc)
#if defined (DIRECTIONAL_COOKIE) || defined (SPOT)
uniform sampler2D _LightTexture0;
// cookie alpha texture map (from Autolight.cginc)
#elif defined (POINT_COOKIE)
uniform samplerCUBE _LightTexture0;
// cookie alpha texture map (from Autolight.cginc)
#endif // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float4 posLight : TEXCOORD1;
// position of the vertex (and fragment) in light space
float3 normalDir : TEXCOORD2;
// surface normal vector in world space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.posLight = mul(_LightMatrix0, output.posWorld);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation = 1.0;
// by default no attenuation with distance #if defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
#elif defined (POINT_NOATT)
lightDirection = normalize(
_WorldSpaceLightPos0 - input.posWorld.xyz);
#elif defined(POINT)||defined(POINT_COOKIE)||defined(SPOT)
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
#endif float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} float cookieAttenuation = 1.0;
// by default no cookie attenuation
#if defined (DIRECTIONAL_COOKIE)
cookieAttenuation = tex2D(_LightTexture0,
input.posLight.xy).a;
#elif defined (POINT_COOKIE)
cookieAttenuation = texCUBE(_LightTexture0,
input.posLight.xyz).a;
#elif defined (SPOT)
cookieAttenuation = tex2D(_LightTexture0,
input.posLight.xy / input.posLight.w
+ float2(0.5, 0.5)).a;
#endif return float4(cookieAttenuation
* (diffuseReflection + specularReflection), 1.0);
} ENDCG
}
}
Fallback "Specular"
}

Per-pixel lighting with cookies

Projectors (about projective texture mapping for projectors)

 Shader "Cg projector shader for adding light" {
Properties {
_ShadowTex ("Projected Image", 2D) = "white" {}
}
SubShader {
Pass {
Blend One One
// add color of _ShadowTex to the color in the framebuffer
ZWrite Off // don't change depths
Offset -, - // avoid depth fighting CGPROGRAM #pragma vertex vert
#pragma fragment frag // User-specified properties
uniform sampler2D _ShadowTex; // Projector-specific uniforms
uniform float4x4 _Projector; // transformation matrix
// from object space to projector space struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posProj : TEXCOORD0;
// position in projector space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.posProj = mul(_Projector, input.vertex);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
if (input.posProj.w > 0.0) // in front of projector?
{
return tex2D(_ShadowTex ,
input.posProj.xy / input.posProj.w);
// alternatively: return tex2Dproj(
// _ShadowTex, input.posProj);
}
else // behind projector
{
return float4(0.0, 0.0, 0.0, 0.0);
}
} ENDCG
}
}
Fallback "Projector/Light"
}

Projector shader for adding light

 // Upgrade NOTE: replaced '_Projector' with 'unity_Projector'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cg projector shader for drop shadows" {
Properties {
_ShadowTex ("Projected Image", 2D) = "white" {}
}
SubShader {
Pass {
Blend Zero OneMinusSrcAlpha // attenuate color in framebuffer
// by 1 minus alpha of _ShadowTex
ZWrite Off // don't change depths
Offset -, - // avoid depth fighting CGPROGRAM #pragma vertex vert
#pragma fragment frag // User-specified properties
uniform sampler2D _ShadowTex; // Projector-specific uniforms
uniform float4x4 unity_Projector; // transformation matrix
// from object space to projector space struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posProj : TEXCOORD0;
// position in projector space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.posProj = mul(unity_Projector, input.vertex);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
if (input.posProj.w > 0.0) // in front of projector?
{
return tex2D(_ShadowTex ,
input.posProj.xy / input.posProj.w);
// alternatively: return tex2Dproj(
// _ShadowTex, input.posProj);
}
else // behind projector
{
return float4(0.0, 0.0, 0.0, 0.0);
}
} ENDCG
}
}
Fallback "Projector/Light"
}

Projector shader for drop shadows

Environment Mapping

Reflecting Surfaces (about reflection mapping)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shader with reflection map" {
Properties {
_Cube("Reflection Map",Cube) = "" {}
}
SubShader{
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // User-specified uniforms
uniform samplerCUBE _Cube; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float3 normalDir:TEXCOORD0;
float3 viewDir:TEXCOORD1;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex); return output;
} float4 frag(vertexOutput input):COLOR{
float3 reflectionDir = reflect(input.viewDir,normalize(input.normalDir));
return texCUBE(_Cube,reflectionDir);
} ENDCG
}
}
}

Shader with reflection map

Curved Glass (about refraction mapping)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shader with refraction mapping" {
Properties {
_Cube("Reflection Map",Cube) = "" {}
}
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag uniform samplerCUBE _Cube; struct vertexInput{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float3 normalDir:TEXCOORD0;
float3 viewDir:TEXCOORD1;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
output.normalDir = normalize(mul(float4(input.normal,0.0),modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
float refractiveIndex = 1.5;
float3 refractedDir = refract(normalize(input.viewDir),normalize(input.normalDir),1.0/refractiveIndex);
return texCUBE(_Cube,refractedDir);
} ENDCG
}
}
}

Shader with refraction mapping

Skyboxes (about rendering of environment maps as background)

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Cg shader for skybox" {
Properties {
_Cube("Environment Map",Cube)=""{}
}
SubShader{
Tags { "Queue" = "Background" }
Pass{
ZWrite Off
Cull Front CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // User-specified uniform
uniform samplerCUBE _Cube; struct vertexInput{
float4 vertex:POSITION;
};
struct vertexOutput{
float4 pos:SV_POSITION;
float3 viewDir:TEXCOORD1;
}; vertexOutput vert(vertexInput input){
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
output.viewDir = mul(modelMatrix,input.vertex).xyz - _WorldSpaceCameraPos;
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input):COLOR{
return texCUBE(_Cube,input.viewDir);
} ENDCG
}
}
}

Shader for skybox

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Cg shader for Unity-specific skybox" {
Properties {
_Cube("Environment Map",Cube)="white"{}
}
SubShader {
Tags {"Queue"="Background"}
Pass{
ZWrite Off
Cull Off CGPROGRAM #pragma vertex vert
#pragma fragment frag // User-specified uniforms
samplerCUBE _Cube; struct vertexInput{
float4 vertex:POSITION;
float3 texcoord:TEXCOORD0;
};
struct vertexOutput{
float4 vertex:SV_POSITION;
float3 texcoord:TEXCOORD0;
}; vertexOutput vert(vertexInput input){
vertexOutput output;
output.vertex = UnityObjectToClipPos(input.vertex);
output.texcoord = input.texcoord;
return output;
} float4 frag(vertexOutput input):COLOR{
return texCUBE(_Cube,input.texcoord);
} ENDCG
}
}
}

Shader for Unity-specific skybox

Many Light Sources (about image-based lighting)

 Shader "Cg shader with image-based diffuse lighting" {
Properties {
_OriginalCube ("Environment Map", Cube) = "" {}
_Cube ("Diffuse Environment Map", Cube) = "" {}
}
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // User-specified uniforms
uniform samplerCUBE _Cube; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normalDir : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return texCUBE(_Cube, input.normalDir);
} ENDCG
}
}
}

Shader with image-based diffuse lighting

Variations on Lighting

Brushed Metal (about anisotropic specular reflection)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg anisotropic per-pixel lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_AlphaX ("Roughness in Brush Direction", Float) = 1.0
_AlphaY ("Roughness orthogonal to Brush Direction", Float) = 1.0
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _AlphaX;
uniform float _AlphaY; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float3 viewDir : TEXCOORD1;
// view direction in world space
float3 normalDir : TEXCOORD2;
// surface normal vector in world space
float3 tangentDir : TEXCOORD3;
// brush direction in world space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.viewDir = normalize(_WorldSpaceCameraPos
- output.posWorld.xyz);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.tangentDir = normalize(
mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 halfwayVector =
normalize(lightDirection + input.viewDir);
float3 binormalDirection =
cross(input.normalDir, input.tangentDir);
float dotLN = dot(lightDirection, input.normalDir);
// compute this dot product only once float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dotLN); float3 specularReflection;
if (dotLN < 0.0) // light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
float dotHN = dot(halfwayVector, input.normalDir);
float dotVN = dot(input.viewDir, input.normalDir);
float dotHTAlphaX =
dot(halfwayVector, input.tangentDir) / _AlphaX;
float dotHBAlphaY = dot(halfwayVector,
binormalDirection) / _AlphaY; specularReflection =
attenuation * _LightColor0.rgb * _SpecColor.rgb
* sqrt(max(0.0, dotLN / dotVN))
* exp(-2.0 * (dotHTAlphaX * dotHTAlphaX
+ dotHBAlphaY * dotHBAlphaY) / (1.0 + dotHN));
}
return float4(ambientLighting + diffuseReflection
+ specularReflection, 1.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _AlphaX;
uniform float _AlphaY; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
// position of the vertex (and fragment) in world space
float3 viewDir : TEXCOORD1;
// view direction in world space
float3 normalDir : TEXCOORD2;
// surface normal vector in world space
float3 tangentDir : TEXCOORD3;
// brush direction in world space
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.viewDir = normalize(_WorldSpaceCameraPos
- output.posWorld.xyz);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.tangentDir = normalize(
mul(modelMatrix, float4(input.tangent.xyz, 0.0)).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 halfwayVector =
normalize(lightDirection + input.viewDir);
float3 binormalDirection =
cross(input.normalDir, input.tangentDir);
float dotLN = dot(lightDirection, input.normalDir);
// compute this dot product only once float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dotLN); float3 specularReflection;
if (dotLN < 0.0) // light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
float dotHN = dot(halfwayVector, input.normalDir);
float dotVN = dot(input.viewDir, input.normalDir);
float dotHTAlphaX =
dot(halfwayVector, input.tangentDir) / _AlphaX;
float dotHBAlphaY = dot(halfwayVector,
binormalDirection) / _AlphaY; specularReflection =
attenuation * _LightColor0.rgb * _SpecColor.rgb
* sqrt(max(0.0, dotLN / dotVN))
* exp(-2.0 * (dotHTAlphaX * dotHTAlphaX
+ dotHBAlphaY * dotHBAlphaY) / (1.0 + dotHN));
}
return float4(diffuseReflection
+ specularReflection, 1.0);
}
ENDCG
}
}
Fallback "Specular"
}

Anisotropic per-pixel lighting

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

 Shader "Custom/Cg Fresnel highlights" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float3x3 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(mul(input.normal, modelMatrixInverse));
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);
float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
float3 halfwayDirection =
normalize(lightDirection + viewDirection);
float w = pow(1.0 - max(0.0,
dot(halfwayDirection, viewDirection)), 5.0);
specularReflection = attenuation * _LightColor0.rgb
* lerp(_SpecColor.rgb, float3(1.0, 1.0, 1.0), w)
* pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
}
return float4(ambientLighting
+ diffuseReflection + specularReflection, 1.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);
float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
float3 halfwayDirection =
normalize(lightDirection + viewDirection);
float w = pow(1.0 - max(0.0,
dot(halfwayDirection, viewDirection)), 5.0);
specularReflection = attenuation * _LightColor0.rgb
* lerp(_SpecColor.rgb, float3(1.0, 1.0, 1.0), w)
* pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
}
return float4(diffuseReflection
+ specularReflection, 1.0);
}
ENDCG
}
}
Fallback "Specular"
}

Fresnel highlights

Diffuse Reflection of Skylight (about hemisphere lighting)

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg per-vertex hemisphere lighting" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_UpperHemisphereColor ("Upper Hemisphere Color", Color)
= (,,,)
_LowerHemisphereColor ("Lower Hemisphere Color", Color)
= (,,,)
_UpVector ("Up Vector", Vector) = (,,,)
}
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // shader properties specified by users
uniform float4 _Color;
uniform float4 _UpperHemisphereColor;
uniform float4 _LowerHemisphereColor;
uniform float4 _UpVector; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
// the hemisphere lighting computed in the vertex shader
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; float3 normalDirection = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
float3 upDirection = normalize(_UpVector); float w = 0.5 * (1.0 + dot(upDirection, normalDirection));
output.col = (w * _UpperHemisphereColor
+ (1.0 - w) * _LowerHemisphereColor) * _Color; output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
}
}
}

Per-vertex hemisphere lighting

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

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg translucent surfaces" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
_DiffuseTranslucentColor ("Diffuse Translucent Color", Color)
= (,,,)
_ForwardTranslucentColor ("Forward Translucent Color", Color)
= (,,,)
_Sharpness ("Sharpness", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source
Cull Off // show frontfaces and backfaces CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _DiffuseTranslucentColor;
uniform float4 _ForwardTranslucentColor;
uniform float _Sharpness; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);
float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz); normalDirection = faceforward(normalDirection,
-viewDirection, normalDirection);
// flip normal if dot(-viewDirection, normalDirection)>0 float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} // Computation of the Phong reflection model: float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} // Computation of the translucent illumination: float3 diffuseTranslucency =
attenuation * _LightColor0.rgb
* _DiffuseTranslucentColor.rgb
* max(0.0, dot(lightDirection, -normalDirection)); float3 forwardTranslucency;
if (dot(normalDirection, lightDirection) > 0.0)
// light source on the wrong side?
{
forwardTranslucency = float3(0.0, 0.0, 0.0);
// no forward-scattered translucency
}
else // light source on the right side
{
forwardTranslucency = attenuation * _LightColor0.rgb
* _ForwardTranslucentColor.rgb * pow(max(0.0,
dot(-lightDirection, viewDirection)), _Sharpness);
} // Computation of the complete illumination: return float4(ambientLighting
+ diffuseReflection + specularReflection
+ diffuseTranslucency + forwardTranslucency, 1.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Cull Off
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _DiffuseTranslucentColor;
uniform float4 _ForwardTranslucentColor;
uniform float _Sharpness; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir);
float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz); normalDirection = faceforward(normalDirection,
-viewDirection, normalDirection);
// flip normal if dot(-viewDirection, normalDirection)>0 float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} // Computation of the Phong reflection model: float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} // Computation of the translucent illumination: float3 diffuseTranslucency =
attenuation * _LightColor0.rgb
* _DiffuseTranslucentColor.rgb
* max(0.0, dot(lightDirection, -normalDirection)); float3 forwardTranslucency;
if (dot(normalDirection, lightDirection) > 0.0)
// light source on the wrong side?
{
forwardTranslucency = float3(0.0, 0.0, 0.0);
// no forward-scattered translucency
}
else // light source on the right side
{
forwardTranslucency = attenuation * _LightColor0.rgb
* _ForwardTranslucentColor.rgb * pow(max(0.0,
dot(-lightDirection, viewDirection)), _Sharpness);
} // Computation of the complete illumination: return float4(diffuseReflection + specularReflection
+ diffuseTranslucency + forwardTranslucency, 1.0);
}
ENDCG
}
}
}

Translucent surfaces

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

 Shader "Custom/Cg translucent bodies" {
Properties {
_Color ("Diffuse Color", Color) = (,,,)
_Waxiness ("Waxiness", Range(,)) =
_SpecColor ("Specular Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
_TranslucentColor ("Translucent Color", Color) = (,,,)
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" } // pass for
// ambient light and first light source on back faces
Cull Front // render back faces only
Blend One Zero // mark rasterized pixels in framebuffer
// with alpha = 0 (usually they should have alpha = 1) CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float _Waxiness;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _TranslucentColor; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting = _TranslucentColor.rgb
* UNITY_LIGHTMODEL_AMBIENT.rgb; float3 diffuseReflection = _TranslucentColor.rgb
* attenuation * _LightColor0.rgb
* max(0.0, dot(normalDirection, lightDirection)); float silhouetteness =
1.0 - abs(dot(viewDirection, normalDirection)); return float4(silhouetteness
* (ambientLighting + diffuseReflection), 0.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources on back faces
Cull Front // render back faces only
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float _Waxiness;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _TranslucentColor; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection = _TranslucentColor.rgb
* attenuation * _LightColor0.rgb
* max(0.0, dot(normalDirection, lightDirection)); float silhouetteness =
1.0 - abs(dot(viewDirection, normalDirection)); return float4(silhouetteness * diffuseReflection, 0.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardBase" } // pass for
// setting pixels that were not rasterized to black
Cull Back // render front faces only (default behavior)
Blend Zero OneMinusDstAlpha // set colors of pixels
// with alpha = 1 to black by multiplying with 1-alpha CGPROGRAM #pragma vertex vert
#pragma fragment frag float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertexPos);
} float4 frag(void) : COLOR
{
return float4(0.0, 0.0, 0.0, 0.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardBase" } // pass for
// ambient light and first light source on front faces
Cull Back // render front faces only
Blend One SrcAlpha // multiply color in framebuffer
// with silhouetteness in fragment's alpha and add colors CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float _Waxiness;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _TranslucentColor; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* (_Waxiness + (1.0 - _Waxiness)
* max(0.0, dot(normalDirection, lightDirection))); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} float silhouetteness =
1.0 - abs(dot(viewDirection, normalDirection)); return float4(ambientLighting + diffuseReflection
+ specularReflection, silhouetteness);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources on front faces
Cull Back // render front faces only
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float _Waxiness;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _TranslucentColor; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* (_Waxiness + (1.0 - _Waxiness)
* max(0.0, dot(normalDirection, lightDirection))); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} float silhouetteness =
1.0 - abs(dot(viewDirection, normalDirection)); return float4(diffuseReflection
+ specularReflection, silhouetteness);
} ENDCG
}
}
Fallback "Specular"
}

Translucent bodies

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

WikiBooks/Cg Programming-LMLPHP

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shadow of sphere" {
Properties {
_Color ("Diffuse Material Color", Color) = (,,,)
_SpecColor ("Specular Material Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
_SpherePosition ("Sphere Position", Vector) = (,,,)
_SphereRadius ("Sphere Radius", Float) =
_LightSourceRadius ("Light Source Radius", Float) = 0.005
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _SpherePosition;
// center of shadow-casting sphere in world coordinates
uniform float _SphereRadius;
// radius of shadow-casting sphere
uniform float _LightSourceRadius;
// in radians for directional light sources struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float lightDistance;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection =
normalize(_WorldSpaceLightPos0.xyz);
lightDistance = 1.0;
}
else // point or spot light
{
lightDirection =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
lightDistance = length(lightDirection);
attenuation = 1.0 / lightDistance; // linear attenuation
lightDirection = lightDirection / lightDistance;
} // computation of level of shadowing w
float3 sphereDirection =
_SpherePosition.xyz - input.posWorld.xyz;
float sphereDistance = length(sphereDirection);
sphereDirection = sphereDirection / sphereDistance;
float d = lightDistance
* (asin(min(1.0,
length(cross(lightDirection, sphereDirection))))
- asin(min(1.0, _SphereRadius / sphereDistance)));
float w = smoothstep(-1.0, 1.0, -d / _LightSourceRadius);
w = w * smoothstep(0.0, 0.2,
dot(lightDirection, sphereDirection));
if (0.0 != _WorldSpaceLightPos0.w) // point light source?
{
w = w * smoothstep(0.0, _SphereRadius,
lightDistance - sphereDistance);
} float3 ambientLighting =
UNITY_LIGHTMODEL_AMBIENT.rgb * _Color.rgb; float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4(ambientLighting
+ (1.0 - w) * (diffuseReflection + specularReflection),
1.0);
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend One One // additive blending CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _SpecColor;
uniform float _Shininess;
uniform float4 _SpherePosition;
// center of shadow-casting sphere in world coordinates
uniform float _SphereRadius;
// radius of shadow-casting sphere
uniform float _LightSourceRadius;
// in radians for directional light sources struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float lightDistance;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
lightDistance = 1.0;
}
else // point or spot light
{
lightDirection =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
lightDistance = length(lightDirection);
attenuation = 1.0 / lightDistance; // linear attenuation
lightDirection = lightDirection / lightDistance;
} // computation of level of shadowing w
float3 sphereDirection =
_SpherePosition.xyz - input.posWorld.xyz;
float sphereDistance = length(sphereDirection);
sphereDirection = sphereDirection / sphereDistance;
float d = lightDistance
* (asin(min(1.0,
length(cross(lightDirection, sphereDirection))))
- asin(min(1.0, _SphereRadius / sphereDistance)));
float w = smoothstep(-1.0, 1.0, -d / _LightSourceRadius);
w = w * smoothstep(0.0, 0.2,
dot(lightDirection, sphereDirection));
if (0.0 != _WorldSpaceLightPos0.w) // point light source?
{
w = w * smoothstep(0.0, _SphereRadius,
lightDistance - sphereDistance);
} float3 diffuseReflection =
attenuation * _LightColor0.rgb * _Color.rgb
* max(0.0, dot(normalDirection, lightDirection)); float3 specularReflection;
if (dot(normalDirection, lightDirection) < 0.0)
// light source on the wrong side?
{
specularReflection = float3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
specularReflection = attenuation * _LightColor0.rgb
* _SpecColor.rgb * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
} return float4((1.0 - w) * (diffuseReflection
+ specularReflection), 1.0);
} ENDCG
}
}
Fallback "Specular"
}

Shadow of sphere

Toon Shading (about non-photorealistic rendering)

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg shader for toon shading" {
Properties {
_Color ("Diffuse Color", Color) = (,,,)
_UnlitColor ("Unlit Diffuse Color", Color) = (0.5,0.5,0.5,)
_DiffuseThreshold ("Threshold for Diffuse Colors", Range(,))
= 0.1
_OutlineColor ("Outline Color", Color) = (,,,)
_LitOutlineThickness ("Lit Outline Thickness", Range(,)) = 0.1
_UnlitOutlineThickness ("Unlit Outline Thickness", Range(,))
= 0.4
_SpecColor ("Specular Color", Color) = (,,,)
_Shininess ("Shininess", Float) =
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" }
// pass for ambient light and first light source CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _UnlitColor;
uniform float _DiffuseThreshold;
uniform float4 _OutlineColor;
uniform float _LitOutlineThickness;
uniform float _UnlitOutlineThickness;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).xyz);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.xyz);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} // default: unlit
float3 fragmentColor = _UnlitColor.rgb; // low priority: diffuse illumination
if (attenuation
* max(0.0, dot(normalDirection, lightDirection))
>= _DiffuseThreshold)
{
fragmentColor = _LightColor0.rgb * _Color.rgb;
} // higher priority: outline
if (dot(viewDirection, normalDirection)
< lerp(_UnlitOutlineThickness, _LitOutlineThickness,
max(0.0, dot(normalDirection, lightDirection))))
{
fragmentColor = _LightColor0.rgb * _OutlineColor.rgb;
} // highest priority: highlights
if (dot(normalDirection, lightDirection) > 0.0
// light source on the right side?
&& attenuation * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess) > 0.5)
// more than half highlight intensity?
{
fragmentColor = _SpecColor.a
* _LightColor0.rgb * _SpecColor.rgb
+ (1.0 - _SpecColor.a) * fragmentColor;
}
return float4(fragmentColor, 1.0);
}
ENDCG
} Pass {
Tags { "LightMode" = "ForwardAdd" }
// pass for additional light sources
Blend SrcAlpha OneMinusSrcAlpha
// blend specular highlights over framebuffer CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
uniform float4 _LightColor0;
// color of light source (from "Lighting.cginc") // User-specified properties
uniform float4 _Color;
uniform float4 _UnlitColor;
uniform float _DiffuseThreshold;
uniform float4 _OutlineColor;
uniform float _LitOutlineThickness;
uniform float _UnlitOutlineThickness;
uniform float4 _SpecColor;
uniform float _Shininess; struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posWorld : TEXCOORD0;
float3 normalDir : TEXCOORD1;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject; output.posWorld = mul(modelMatrix, input.vertex);
output.normalDir = normalize(
mul(float4(input.normal, 0.0), modelMatrixInverse).rgb);
output.pos = UnityObjectToClipPos(input.vertex);
return output;
} float4 frag(vertexOutput input) : COLOR
{
float3 normalDirection = normalize(input.normalDir); float3 viewDirection = normalize(
_WorldSpaceCameraPos - input.posWorld.rgb);
float3 lightDirection;
float attenuation; if (0.0 == _WorldSpaceLightPos0.w) // directional light?
{
attenuation = 1.0; // no attenuation
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
}
else // point or spot light
{
float3 vertexToLightSource =
_WorldSpaceLightPos0.xyz - input.posWorld.xyz;
float distance = length(vertexToLightSource);
attenuation = 1.0 / distance; // linear attenuation
lightDirection = normalize(vertexToLightSource);
} float4 fragmentColor = float4(0.0, 0.0, 0.0, 0.0);
if (dot(normalDirection, lightDirection) > 0.0
// light source on the right side?
&& attenuation * pow(max(0.0, dot(
reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess) > 0.5)
// more than half highlight intensity?
{
fragmentColor =
float4(_LightColor0.rgb, 1.0) * _SpecColor;
}
return fragmentColor;
}
ENDCG
}
}
Fallback "Specular"
}

Shader for toon shading

Non-Standard Vertex Transformations

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

 Shader "Custom/Cg shader for screen overlays" {
Properties {
_MainTex ("Texture", Rect) = "white" {}
_Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
_X ("X", Float) = 0.0
_Y ("Y", Float) = 0.0
_Width ("Width", Float) =
_Height ("Height", Float) =
}
SubShader {
Tags { "Queue" = "Overlay" } // render after everything else Pass {
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
ZTest Always // deactivate depth test CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc"
// defines float4 _ScreenParams with x = width;
// y = height; z = 1 + 1.0/width; w = 1 + 1.0/height
// and defines float4 _ProjectionParams
// with x = 1 or x = -1 for flipped projection matrix;
// y = near clipping plane; z = far clipping plane; and
// w = 1 / far clipping plane // User-specified uniforms
uniform sampler2D _MainTex;
uniform float4 _Color;
uniform float _X;
uniform float _Y;
uniform float _Width;
uniform float _Height; struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float2 rasterPosition = float2(
_X + _ScreenParams.x / 2.0
+ _Width * (input.vertex.x + 0.5),
_Y + _ScreenParams.y / 2.0
+ _Height * (input.vertex.y + 0.5));
output.pos = float4(
2.0 * rasterPosition.x / _ScreenParams.x - 1.0,
_ProjectionParams.x * (2.0 * rasterPosition.y / _ScreenParams.y - 1.0),
_ProjectionParams.y, // near plane is at -1.0 or at 0.0
1.0); output.tex = float4(input.vertex.x + 0.5,
input.vertex.y + 0.5, 0.0, 0.0);
// for a cube, vertex.x and vertex.y
// are -0.5 or 0.5
return output;
} float4 frag(vertexOutput input) : COLOR
{
return _Color * tex2D(_MainTex, input.tex.xy);
} ENDCG
}
}
}

Shader for screen overlays

Billboards (about view-aligned projection of objects)

 Shader "Custom/Cg  shader for billboards" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
_ScaleX ("Scale X", Float) = 1.0
_ScaleY ("Scale Y", Float) = 1.0
}
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag // User-specified uniforms
uniform sampler2D _MainTex;
uniform float _ScaleX;
uniform float _ScaleY; struct vertexInput {
float4 vertex : POSITION;
float4 tex : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; output.pos = mul(UNITY_MATRIX_P,
mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0))
+ float4(input.vertex.x, input.vertex.y, 0.0, 0.0)
* float4(_ScaleX, _ScaleY, 1.0, 1.0)); output.tex = input.tex; return output;
} float4 frag(vertexOutput input) : COLOR
{
return tex2D(_MainTex, float2(input.tex.xy));
} ENDCG
}
}
}

Shader for billboards

Nonlinear Deformations (about vertex blending)

 Shader "Custom/Cg shader for vertex blending" {
SubShader {
Pass {
CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // Uniforms set by a script
uniform float4x4 _Trafo0; // model transformation of bone0
uniform float4x4 _Trafo1; // model transformation of bone1 struct vertexInput {
float4 vertex : POSITION;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 col : COLOR;
}; vertexOutput vert(vertexInput input)
{
vertexOutput output; float weight0 = input.vertex.z + 0.5;
// depends on the mesh
float4 blendedVertex =
weight0 * mul(_Trafo0, input.vertex)
+ (1.0 - weight0) * mul(_Trafo1, input.vertex); output.pos = mul(UNITY_MATRIX_VP, blendedVertex); output.col = float4(weight0, 1.0 - weight0, 0.0, 1.0);
// visualize weight0 as red and weight1 as green
return output;
} float4 frag(vertexOutput input) : COLOR
{
return input.col;
} ENDCG
}
}
}

Shader for vertex blending

Shadows on Planes (about projecting shadows onto planes)

 // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' Shader "Custom/Cg planar shadow" {
Properties {
_Color ("Object's Color", Color) = (,,,)
_ShadowColor ("Shadow's Color", Color) = (,,,)
}
SubShader {
Pass {
Tags { "LightMode" = "ForwardBase" } // rendering of object CGPROGRAM #pragma vertex vert
#pragma fragment frag // User-specified properties
uniform float4 _Color; float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
return UnityObjectToClipPos(vertexPos);
} float4 frag(void) : COLOR
{
return _Color;
} ENDCG
} Pass {
Tags { "LightMode" = "ForwardBase" }
// rendering of projected shadow
Offset -1.0, -2.0
// make sure shadow polygons are on top of shadow receiver CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "UnityCG.cginc" // User-specified uniforms
uniform float4 _ShadowColor;
uniform float4x4 _World2Receiver; // transformation from
// world coordinates to the coordinate system of the plane float4 vert(float4 vertexPos : POSITION) : SV_POSITION
{
float4x4 modelMatrix = unity_ObjectToWorld;
float4x4 modelMatrixInverse = unity_WorldToObject;
float4x4 viewMatrix =
mul(UNITY_MATRIX_MV, modelMatrixInverse); float4 lightDirection;
if (0.0 != _WorldSpaceLightPos0.w)
{
// point or spot light
lightDirection = normalize(
mul(modelMatrix, vertexPos - _WorldSpaceLightPos0));
}
else
{
// directional light
lightDirection = -normalize(_WorldSpaceLightPos0);
} float4 vertexInWorldSpace = mul(modelMatrix, vertexPos);
float4 world2ReceiverRow1 =
float4(_World2Receiver[][], _World2Receiver[][],
_World2Receiver[][], _World2Receiver[][]);
float distanceOfVertex =
dot(world2ReceiverRow1, vertexInWorldSpace);
// = (_World2Receiver * vertexInWorldSpace).y
// = height over plane
float lengthOfLightDirectionInY =
dot(world2ReceiverRow1, lightDirection);
// = (_World2Receiver * lightDirection).y
// = length in y direction if (distanceOfVertex > 0.0 && lengthOfLightDirectionInY < 0.0)
{
lightDirection = lightDirection
* (distanceOfVertex / (-lengthOfLightDirectionInY));
}
else
{
lightDirection = float4(0.0, 0.0, 0.0, 0.0);
// don't move vertex
} return mul(UNITY_MATRIX_VP,
vertexInWorldSpace + lightDirection);
} float4 frag(void) : COLOR
{
return _ShadowColor;
} ENDCG
}
}
}

Planar shadow

Image Effects and Compute Shaders

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

 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

 Shader "Custom/tintImageEffectShader"
{
Properties
{
_MainTex ("Source", 2D) = "white" {}
_Color ("Tint", Color) = (,,,)
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always Pass
{
CGPROGRAM
#pragma vertex vertexShader
#pragma fragment fragmentShader #include "UnityCG.cginc" struct vertexInput
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
}; struct vertexOutput
{
float2 texcoord : TEXCOORD0;
float4 position : SV_POSITION;
}; vertexOutput vertexShader(vertexInput i)
{
vertexOutput o;
o.position = UnityObjectToClipPos(i.vertex);
o.texcoord = i.texcoord;
return o;
} sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color; float4 fragmentShader(vertexOutput i) : COLOR
{
float4 color = tex2D(_MainTex,
UnityStereoScreenSpaceUVAdjust(
i.texcoord, _MainTex_ST));
return color * _Color;
}
ENDCG
}
}
Fallback Off
}

TintImageEffectShader

Miscellaneous

General Cg Topics

Overview of the Programmable Graphics Pipeline

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

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

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

Rasterization (Interpolation of Per-Fragment Varying Parameters)

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

Anti-Aliasing Techniques

Phong Reflection Model

05-11 11:37
查看更多