ReliefDiffuse
m (Text replace - "<shaderlab>" to "<syntaxhighlight lang="shaderlab">") |
m (Text replace - "</shaderlab>" to "</syntaxhighlight>") |
||
| Line 241: | Line 241: | ||
FallBack "Parallax Diffuse" | FallBack "Parallax Diffuse" | ||
} | } | ||
| − | </ | + | </syntaxhighlight> |
Latest revision as of 23:56, 17 January 2012
Author: Nils Daumann.
Contents |
[edit] Description
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.
[edit] Usage
- 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).
[edit] Download
[edit] 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"
}