Skip to content

Instantly share code, notes, and snippets.

@nevarman
Created June 8, 2015 07:27
Show Gist options
  • Save nevarman/d10b5101ca93ba3f6646 to your computer and use it in GitHub Desktop.
Save nevarman/d10b5101ca93ba3f6646 to your computer and use it in GitHub Desktop.
// Shader for Unity integration with SpriteLamp
// Copyright (c) 2014 Steve Karolewics & Indreams Studios
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
Shader "Custom/SpriteLamp"
{
Properties
{
_MainTex ("Diffuse Texture", 2D) = "white" {}
_Normal ("Normal", 2D) = "bump" {}
_Depth ("Depth", 2D) = "gray" {}
_SpecColor ("Specular Material Color", Color) = (1,1,1,1)
_Shininess ("Shininess", Float) = 10
_AmplifyDepth ("Amplify Depth", Float) = 1
_CelShadingLevels ("Cel Shading Levels", Float) = 0
}
SubShader
{
AlphaTest NotEqual 0.0
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// User-specified properties
uniform sampler2D _MainTex;
struct VertexInput
{
float4 vertex : POSITION;
float4 color : COLOR;
float4 uv : TEXCOORD0;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
};
VertexOutput vert(VertexInput input)
{
VertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.color = input.color;
output.uv = float2(input.uv);
return output;
}
float4 frag(VertexOutput input) : COLOR
{
float4 diffuseColor = tex2D(_MainTex, input.uv);
float3 ambientLighting = float3(UNITY_LIGHTMODEL_AMBIENT) * float3(diffuseColor) *
float3(input.color);
return float4(ambientLighting, diffuseColor.a);
}
ENDCG
}
Pass
{
Tags { "LightMode" = "ForwardAdd" }
Blend One One // additive blending
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// User-specified properties
uniform sampler2D _MainTex;
uniform sampler2D _Normal;
uniform sampler2D _Depth;
uniform float4 _SpecColor;
uniform float4 _LightColor0;
uniform float _Shininess;
uniform float _AmplifyDepth;
uniform float _CelShadingLevels;
struct VertexInput
{
float4 vertex : POSITION;
float4 color : COLOR;
float4 uv : TEXCOORD0;
};
struct VertexOutput
{
float4 pos : POSITION;
float4 color : COLOR;
float2 uv : TEXCOORD0;
float4 posWorld : TEXCOORD1;
};
VertexOutput vert(VertexInput input)
{
VertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.posWorld = mul(_Object2World, input.vertex);
output.uv = float2(input.uv);
output.color = input.color;
return output;
}
float4 frag(VertexOutput input) : COLOR
{
float4 diffuseColor = tex2D(_MainTex, input.uv);
// To compute the correct normal:
// 1) Get the pixel value from the normal map
// 2) Subtract 0.5 and multiply by 2 to convert from the range 0...1 to -1...1
// 3) Multiply by world to object matrix, to handle rotation, etc
// 4) Negate Z so that lighting works as expected (sprites further away from the camera than
// a light are lit, etc.)
// 5) Normalize
float3 normalDirection = (tex2D(_Normal, input.uv).xyz - 0.5f) * 2.0f;
normalDirection = float3(mul(float4(normalDirection, 1.0f), _World2Object));
normalDirection.z *= -1;
normalDirection = normalize(normalDirection);
// To adjust depth:
// 1) Get the depth value from the depth map
// 2) Subtract 0.5 and multiply by 2 to convert from the range 0...1 to -1...1
// 3) Multiply by the amplify depth value, and subtract from the fragment's z position
float depthColor = (tex2D(_Depth, input.uv).x - 0.5f) * 2.0f;
float3 posWorld = float3(input.posWorld);
posWorld.z -= depthColor * _AmplifyDepth;
float3 vertexToLightSource = float3(_WorldSpaceLightPos0) - posWorld;
float distance = length(vertexToLightSource);
// The values for attenuation and lightDirection are assuming point lights
float attenuation = 1.0 / distance; // Linear attenuation is good enough for now
float3 lightDirection = normalize(vertexToLightSource);
// Compute diffuse part of lighting
float normalDotLight = dot(normalDirection, lightDirection);
float diffuseLevel = attenuation * max(0.0f, normalDotLight);
// Compute specular part of lighting
float specularLevel;
if (normalDotLight < 0.0f)
{
// Light is on the wrong side, no specular reflection
specularLevel = 0.0f;
}
else
{
// For orthographic cameras, the view direction is always known
float3 viewDirection = float3(0.0f, 0.0f, -1.0f);
specularLevel = attenuation * pow(max(0.0, dot(reflect(-lightDirection, normalDirection),
viewDirection)), _Shininess);
}
// Add cel-shading if enough levels were specified
if (_CelShadingLevels >= 2)
{
diffuseLevel = floor(diffuseLevel * _CelShadingLevels) / (_CelShadingLevels - 0.5f);
specularLevel = floor(specularLevel * _CelShadingLevels) / (_CelShadingLevels - 0.5f);
}
float3 diffuseReflection = float3(diffuseColor) * input.color *
float3(_LightColor0) * diffuseLevel;
float3 specularReflection = float3(_LightColor0) * float3(_SpecColor) *
input.color * specularLevel;
return float4(diffuseReflection + specularReflection, diffuseColor.a);
}
ENDCG
}
}
// The definition of a fallback shader should be commented out
// during development:
// Fallback "Transparent/Diffuse"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment