From Unify Community Wiki
Jump to: navigation, search

Author: Ricardo A



Example of what the shader does : Lightmaps + Point light in base pass

These are a shader+script to render objects using Lightmaps and an extra point light, in Forward mode (mobile) all in the base pass.



  • Create a material that uses the shader below (Mobile/Bumped Specular Point Light)
  • Add the "SetPointLightData.cs" script to a GameObject. The script executes in Edit Mode.

ShaderLab - LightmapsAndPoint.shader

Invalid language.

You need to specify a language like this: <source lang="html4strict">...</source>

Supported languages for syntax highlighting:

4cs, 6502acme, 6502kickass, 6502tasm, 68000devpac, abap, actionscript, actionscript3, ada, algol68, apache, applescript, apt_sources, asm, asp, autoconf, autohotkey, autoit, avisynth, awk, bascomavr, bash, basic4gl, bf, bibtex, blitzbasic, bnf, boo, c, c_loadrunner, c_mac, caddcl, cadlisp, cfdg, cfm, chaiscript, cil, clojure, cmake, cobol, coffeescript, cpp, cpp-qt, csharp, css, cuesheet, d, dcs, delphi, diff, div, dos, dot, e, ecmascript, eiffel, email, epc, erlang, euphoria, f1, falcon, fo, fortran, freebasic, fsharp, gambas, gdb, genero, genie, gettext, glsl, gml, gnuplot, go, groovy, gwbasic, haskell, hicest, hq9plus, html4strict, html5, icon, idl, ini, inno, intercal, io, j, java, java5, javascript, jquery, kixtart, klonec, klonecpp, latex, lb, lisp, llvm, locobasic, logtalk, lolcode, lotusformulas, lotusscript, lscript, lsl2, lua, m68k, magiksf, make, mapbasic, matlab, mirc, mmix, modula2, modula3, mpasm, mxml, mysql, newlisp, nsis, oberon2, objc, objeck, ocaml, ocaml-brief, oobas, oracle11, oracle8, oxygene, oz, pascal, pcre, per, perl, perl6, pf, php, php-brief, pic16, pike, pixelbender, pli, plsql, postgresql, povray, powerbuilder, powershell, proftpd, progress, prolog, properties, providex, purebasic, pycon, python, q, qbasic, rails, rebol, reg, robots, rpmspec, rsplus, ruby, sas, scala, scheme, scilab, sdlbasic, smalltalk, smarty, sql, systemverilog, tcl, teraterm, text, thinbasic, tsql, typoscript, unicon, uscript, vala, vb, vbnet, verilog, vhdl, vim, visualfoxpro, visualprolog, whitespace, whois, winbatch, xbasic, xml, xorg_conf, xpp, yaml, z80, zxbasic

// Lightmaps and a single point light in forward base pass

Shader "Mobile/Bumped Specular Point Light" {
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1) 
		_Specular ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
		_Shininess ("Shininess", Range (0.01, 1)) = 0.5
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_BumpMap ("Normalmap", 2D) = "bump" {}

	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 300

	Pass {
		Name "FORWARD"
		Tags { "LightMode" = "ForwardBase" }

			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#pragma multi_compile_fwdbase novertexlight
			#include "HLSLSupport.cginc"
			#include "UnityCG.cginc"
			#include "Lighting.cginc"  
			#include "AutoLight.cginc"
			#define INTERNAL_DATA
 			// To debug
			//#pragma debug

			sampler2D _MainTex;
			sampler2D _BumpMap; 
			fixed4 _MainTex_ST;
			fixed4 _BumpMap_ST;			
			fixed4 _Color; 
			fixed4 _Specular;
			fixed _Shininess;
 			// Light & Camera
			uniform fixed4 _worldSpaceLightPosition;
			uniform fixed4 _worldSpaceViewPos;
			uniform fixed4 _lightColor;
			uniform fixed _lightRange;
			uniform fixed _lightIntensity;

			#ifdef LIGHTMAP_OFF
				struct v2f {
					float4 pos : SV_POSITION;
					fixed4 pack0 : TEXCOORD0;
					fixed4 lightDir : TEXCOORD1;
  					fixed3 viewDir : TEXCOORD2;
			#ifndef LIGHTMAP_OFF
				struct v2f {
					float4 pos : SV_POSITION;
					fixed4 pack0 : TEXCOORD0;
					fixed2 lmap : TEXCOORD1;
					fixed4 lightDir : TEXCOORD2;
  					fixed3 viewDir : TEXCOORD3;
				sampler2D unity_Lightmap;
				fixed4 unity_LightmapST;	

			v2f vert (appdata_full v) {
				v2f o;
				o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
				o.pack0.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.pack0.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
   				// Computes object space light direction
				fixed3 objSpaceLightPos = mul(_World2Object, _worldSpaceLightPosition).xyz;
				objSpaceLightPos = objSpaceLightPos.xyz - v.vertex.xyz;
				fixed3 lightDir = mul (rotation, objSpaceLightPos);
				o.lightDir.rgb = lightDir;
				o.lightDir.a = dot(objSpaceLightPos, objSpaceLightPos);
				// Computes object space view direction
				fixed3 objSpaceCameraPos = mul(_World2Object, fixed4(_worldSpaceViewPos.xyz, 1)).xyz * unity_Scale.w;
				objSpaceCameraPos = objSpaceCameraPos - v.vertex.xyz;
				fixed3 viewDirForLight = mul (rotation, objSpaceCameraPos);
				o.viewDir = viewDirForLight;		
   				// Lightmap coordinates
				#ifndef LIGHTMAP_OFF
					o.lmap.xy = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
				return o;
			fixed4 frag (v2f IN) : COLOR {
				fixed2 uv_MainTex = IN.pack0.xy;
				fixed2 uv_BumpMap = IN.pack0.zw;
				// Texture & Normal
				fixed4 albedo_alpha = tex2D(_MainTex, uv_MainTex) * _Color;
				fixed3 Normal = normalize(UnpackNormal(tex2D(_BumpMap, uv_BumpMap)));
				// Blinn Phong
				fixed3 h = normalize (IN.lightDir.rgb + IN.viewDir);
				fixed diff = max (0, dot (Normal, IN.lightDir.rgb));
				fixed nh = max (0, dot (Normal, h));
				fixed spec = pow (nh, _Shininess*128.0f) * albedo_alpha.a;
				fixed atten = 1.0f / (1.0f + (25.0f * IN.lightDir.a / (_lightRange * _lightRange)));
				fixed4 c;
				c.rgb = (albedo_alpha.rgb * _lightColor.rgb * _lightIntensity * diff + _lightColor.rgb * _lightIntensity * _Specular.rgb * spec) * (atten * 2);
				c.a = albedo_alpha.a + _lightColor.a * _Specular.a * spec * atten;
				#ifndef LIGHTMAP_OFF
					fixed4 lmtex = tex2D(unity_Lightmap, IN.lmap.xy);
					fixed3 lm = DecodeLightmap (lmtex);
					c.rgb += albedo_alpha.rgb * lm;
					c.a += albedo_alpha.a;
				#endif // LIGHTMAP_OFF
				return c;
	Fallback "Mobile/Diffuse"

C# - SetPointLightData.cs

using UnityEngine;
// This sets the light's data to be used by the shader. It need to be done this way, because Unity doesn't provide the point light information for the base pass
[ExecuteInEditMode] // Live update when not in Play mode
public class SetPointLightData : MonoBehaviour {
    public new Light pointLight;
    Transform t;
    void Start() {
        t = pointLight.transform;
    void OnPreRender() {
        Vector3 pos = t.position;
		if (pointLight.enabled && pointLight.gameObject.active) {
			Shader.SetGlobalVector("_worldSpaceLightPosition", new Vector4(pos.x, pos.y, pos.z, 0));
			Shader.SetGlobalVector("_worldSpaceViewPos", Camera.mainCamera.transform.position);
			Shader.SetGlobalVector("_lightColor", pointLight.color);
			Shader.SetGlobalFloat("_lightRange", pointLight.range);
			Shader.SetGlobalFloat("_lightIntensity", pointLight.intensity);
		else {
			Shader.SetGlobalFloat("_lightIntensity", 0);
Personal tools