ReliefDiffuse

From Unify Community Wiki
Jump to: navigation, search


Author: Nils Daumann.

Contents

Description

The shader in action.
Comparision of this shader with the builtin diffuse one.

This is a basic relief mapping shader with per pixel lighting based on a tangent space normalmap.

Works on shader model 3.0 capable cards. Supports fog and shadows.


Usage

Typical setup

  • Color is the general color of the material.
  • Height is a slider which adjusts how deep the heightmaps black pixels actually are (at least indirectly ;)).
  • Texture is mapped on the object using its uv set (Tiling and Offset works!).
  • Normalmap is a tangent space normalmap used for the lighting (put it into a textures RGB channels).
  • Heightmap is a grayscale heightmap defining the shape of the surface (put it into the same textures alpha channel).
  • You can adjust the speed and quality of the shader by adjusting the LINEAR_SEARCH and BINARY_SEARCH values in both passes. Higher values can slow it down a lot and also result in an error, but cause a higher quality (you should usually just stick to the default ones).


Download

Media:ReliefDiffuse.zip


ShaderLab - ReliefDiffuse.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


Shader "Relief Diffuse"
{
	Properties
	{
		_Color("Color", Color) = (0.5, 0.5, 0.5, 1)
		_Height("Height", Range(0, 0.2)) = 0.05
		_MainTex("Texture (RGB)", 2D) = "white" {}
		_NormalTex("Normalmap (RGB), Heightmap (A)", 2D) = "white" {}
	}
	
	SubShader
	{
		Pass
		{
			Name "BASE"
			Tags {"LightMode" = "Always"}
			
			CGPROGRAM
				#pragma target 3.0
				#pragma profileoption MaxTexIndirections=256
				
				#pragma vertex vert
				#pragma fragment frag
				
				#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				
				#include "UnityCG.cginc"
				
				#define LINEAR_SEARCH 20
				#define BINARY_SEARCH 10
				
				uniform sampler2D _MainTex;
				uniform float4 _MainTex_ST;
				uniform sampler2D _NormalTex;
				uniform float4 _NormalTex_ST;
				uniform float _Height;
				
				struct v2f
				{
					V2F_POS_FOG;
					float4 texcoord;
					float3 viewdir;
				}; 

				v2f vert(appdata_tan v)
				{
					v2f o;
					
					PositionFog(v.vertex, o.pos, o.fog);
					o.texcoord.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
					o.texcoord.zw = TRANSFORM_TEX(v.texcoord, _NormalTex);
					
					TANGENT_SPACE_ROTATION;
					o.viewdir = _ObjectSpaceCameraPos-v.vertex;
					o.viewdir = mul(rotation, o.viewdir);
					
					return o;
				}
				
				float ray_intersect_rm(in sampler2D reliefmap, in float2 dp, in float2 ds, in float  bias)
				{
					float size = 1.0/LINEAR_SEARCH; // current size of search window
					float depth = -bias;// current depth position
					int i;
					for(i = 0; i < LINEAR_SEARCH-1; i++)// search front to back for first point inside object 
					{
						float4 t = tex2D(reliefmap,dp+ds*depth).a;
						
						if(depth < t.w-bias)
							depth += size;
					}
					
					for(i = 0; i < BINARY_SEARCH; i++) // recurse around first point (depth) for closest match
					{
						size*=0.5;
						
						float4 t = tex2D(reliefmap,dp+ds*depth).a;
						
						if(depth < t.w-bias)
							depth += (2*size);
						
						depth -= size;
					}
					
					return depth;
				}
				
				float4 frag(v2f i) : COLOR
				{
					i.viewdir = normalize(i.viewdir);
					float2 view = i.viewdir.xy*_Height;
					float depth = ray_intersect_rm(_NormalTex, i.texcoord.zw, view, 1.0f);

					i.texcoord.xy += view*depth;
					float4 color = tex2D(_MainTex, i.texcoord.xy);
					
					return float4(color.rgb*_PPLAmbient, 1.0);
				}
			ENDCG
		}
		
		Pass
		{
			Name "BASE"
			Tags {"LightMode" = "Pixel"}
			Blend AppSrcAdd AppDstAdd
			
			CGPROGRAM
				#pragma target 3.0
				#pragma profileoption MaxTexIndirections=256
				
				#pragma vertex vert
				#pragma fragment frag
				
				#pragma multi_compile_builtin
				#pragma fragmentoption ARB_fog_exp2
				#pragma fragmentoption ARB_precision_hint_fastest
				
				#include "UnityCG.cginc"
				#include "AutoLight.cginc"
				
				#define LINEAR_SEARCH 20
				#define BINARY_SEARCH 10
				
				uniform sampler2D _MainTex;
				uniform float4 _MainTex_ST;
				uniform sampler2D _NormalTex;
				uniform float4 _NormalTex_ST;
				uniform float _Height;
				
				struct v2f
				{
					V2F_POS_FOG;
					LIGHTING_COORDS
					float4 texcoord;
					float3 viewdir;
					float3 lightdir;
				}; 

				v2f vert(appdata_tan v)
				{
					v2f o;
					
					PositionFog(v.vertex, o.pos, o.fog);
					o.texcoord.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
					o.texcoord.zw = TRANSFORM_TEX(v.texcoord, _NormalTex);
					
					TANGENT_SPACE_ROTATION;
					o.viewdir = _ObjectSpaceCameraPos-v.vertex;
					o.viewdir = mul(rotation, o.viewdir);
					
					o.lightdir = ObjSpaceLightDir(v.vertex);
					o.lightdir = mul(rotation, o.lightdir);
					
					TRANSFER_VERTEX_TO_FRAGMENT(o);
					
					return o;
				}
				
				float ray_intersect_rm(in sampler2D reliefmap, in float2 dp, in float2 ds, in float  bias)
				{
					float size = 1.0/LINEAR_SEARCH; // current size of search window
					float depth = -bias;// current depth position
					int i;
					for(i = 0; i < LINEAR_SEARCH-1; i++)// search front to back for first point inside object 
					{
						float4 t = tex2D(reliefmap,dp+ds*depth).a;
						
						if(depth < t.w-bias)
							depth += size;
					}
					
					for(i = 0; i < BINARY_SEARCH; i++) // recurse around first point (depth) for closest match
					{
						size*=0.5;
						
						float4 t = tex2D(reliefmap,dp+ds*depth).a;
						
						if(depth < t.w-bias)
							depth += (2*size);
						
						depth -= size;
					}
					
					return depth;
				}
				
				float4 frag(v2f i) : COLOR
				{
					i.viewdir = normalize(i.viewdir);
					float2 view = i.viewdir.xy*_Height;
					float depth = ray_intersect_rm(_NormalTex, i.texcoord.zw, view, 1.0f);

					float2 offset = view*depth;
					float4 color = tex2D(_MainTex, i.texcoord.xy+offset);
					
					float4 normal = tex2D(_NormalTex, i.texcoord.zw+offset);
					normal.rgb = normalize(normal*2.0-1.0);
					
					return DiffuseLight(i.lightdir, normal.rgb, color, LIGHT_ATTENUATION(i));
				}
			ENDCG
		}
	}
	
	FallBack "Parallax Diffuse"
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Tools