Browse Source

Added simple swaying vegetation example shader.

Lasse Öörni 12 years ago
parent
commit
a698776a66

+ 143 - 0
Bin/CoreData/Shaders/GLSL/Vegetation.frag

@@ -0,0 +1,143 @@
+#include "Uniforms.frag"
+#include "Samplers.frag"
+#include "Lighting.frag"
+#include "Fog.frag"
+
+varying vec2 vTexCoord;
+#ifdef PERPIXEL
+    varying vec4 vLightVec;
+    #ifdef SPECULAR
+        varying vec3 vEyeVec;
+    #endif
+    #ifndef NORMALMAP
+        varying vec3 vNormal;
+    #endif
+    #ifdef SHADOW
+        varying vec4 vShadowPos[NUMCASCADES];
+    #endif
+    #ifdef SPOTLIGHT
+        varying vec4 vSpotPos;
+    #endif
+    #ifdef POINTLIGHT
+        varying vec3 vCubeMaskVec;
+    #endif
+#else
+    varying vec4 vVertexLight;
+    varying vec3 vNormal;
+    #ifdef NORMALMAP
+        varying vec3 vTangent;
+        varying vec3 vBitangent;
+    #endif
+    varying vec4 vScreenPos;
+#endif
+
+void main()
+{
+    // Get material diffuse albedo
+    #ifdef DIFFMAP
+        vec4 diffInput = texture2D(sDiffMap, vTexCoord);
+        #ifdef ALPHAMASK
+            if (diffInput.a < 0.5)
+                discard;
+        #endif
+        vec4 diffColor = cMatDiffColor * diffInput;
+    #else
+        vec4 diffColor = cMatDiffColor;
+    #endif
+    
+    // Get material specular albedo
+    #ifdef SPECMAP
+        vec3 specColor = cMatSpecColor.rgb * texture2D(sSpecMap, vTexCoord).rgb;
+    #else
+        vec3 specColor = cMatSpecColor.rgb;
+    #endif
+
+    #if defined(PERPIXEL)
+        // Per-pixel forward lighting
+        vec3 lightColor;
+        vec3 lightDir;
+        vec3 finalColor;
+        float diff;
+
+        #ifdef NORMALMAP
+            vec3 normal = DecodeNormal(texture2D(sNormalMap, vTexCoord));
+        #else
+            vec3 normal = normalize(vNormal);
+        #endif
+    
+        diff = GetDiffuse(normal, vLightVec.xyz, lightDir);
+    
+        #ifdef SHADOW
+            diff *= GetShadow(vShadowPos, vLightVec.w);
+        #endif
+    
+        #if defined(SPOTLIGHT)
+            lightColor = vSpotPos.w > 0.0 ? texture2DProj(sLightSpotMap, vSpotPos).rgb * cLightColor.rgb : vec3(0.0, 0.0, 0.0);
+        #elif defined(CUBEMASK)
+            lightColor = textureCube(sLightCubeMap, vCubeMaskVec).rgb * cLightColor.rgb;
+        #else
+            lightColor = cLightColor.rgb;
+        #endif
+    
+        #ifdef SPECULAR
+            float spec = GetSpecular(normal, vEyeVec, lightDir, cMatSpecColor.a);
+            finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
+        #else
+            finalColor = diff * lightColor * diffColor.rgb;
+        #endif
+    
+        #ifdef AMBIENT
+            finalColor += cAmbientColor * diffColor.rgb;
+            gl_FragColor = vec4(GetFog(finalColor, vLightVec.w), diffColor.a);
+        #else
+            gl_FragColor = vec4(GetLitFog(finalColor, vLightVec.w), diffColor.a);
+        #endif
+    #elif defined(PREPASS)
+        // Fill light pre-pass G-Buffer
+        #ifdef NORMALMAP
+            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
+            vec3 normal = tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord.xy));
+        #else
+            vec3 normal = vNormal;
+        #endif
+    
+        float specPower = cMatSpecColor.a / 255.0;
+        
+        gl_FragData[0] = vec4(normal * 0.5 + 0.5, specPower);
+        gl_FragData[1] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+    #elif defined(DEFERRED)
+        // Fill deferred G-buffer
+        #ifdef NORMALMAP
+            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
+            vec3 normal = tbn * DecodeNormal(texture2D(sNormalMap, vTexCoord));
+        #else
+            vec3 normal = vNormal;
+        #endif
+
+        float specIntensity = specColor.g;
+        float specPower = cMatSpecColor.a / 255.0;
+
+        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
+
+        gl_FragData[0] = vec4(GetFog(finalColor * diffColor.rgb, vVertexLight.a), 1.0);
+        gl_FragData[1] = GetFogFactor(vVertexLight.a) * vec4(diffColor.rgb, specIntensity);
+        gl_FragData[2] = vec4(normal * 0.5 + 0.5, specPower);
+        gl_FragData[3] = vec4(EncodeDepth(vVertexLight.a), 0.0);
+
+
+    #else
+        // Ambient & per-vertex lighting
+        vec3 finalColor = vVertexLight.rgb * diffColor.rgb;
+
+        #ifdef MATERIAL
+            // Add light pre-pass accumulation result
+            // Lights are accumulated at half intensity. Bring back to full intensity now
+            vec4 lightInput = 2.0 * texture2DProj(sLightBuffer, vScreenPos);
+            vec3 lightSpecColor = lightInput.a * lightInput.rgb / max(GetIntensity(lightInput.rgb), 0.001);
+
+            finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
+        #endif
+
+        gl_FragColor = vec4(GetFog(finalColor, vVertexLight.a), diffColor.a);
+    #endif
+}

+ 114 - 0
Bin/CoreData/Shaders/GLSL/Vegetation.vert

@@ -0,0 +1,114 @@
+#include "Uniforms.vert"
+#include "Transform.vert"
+#include "ScreenPos.vert"
+#include "Lighting.vert"
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform vec2 cWindWorldSpacing;
+
+varying vec2 vTexCoord;
+#ifdef PERPIXEL
+    varying vec4 vLightVec;
+    #ifdef SPECULAR
+        varying vec3 vEyeVec;
+    #endif
+    #ifndef NORMALMAP
+        varying vec3 vNormal;
+    #endif
+    #ifdef SHADOW
+        varying vec4 vShadowPos[NUMCASCADES];
+    #endif
+    #ifdef SPOTLIGHT
+        varying vec4 vSpotPos;
+    #endif
+    #ifdef POINTLIGHT
+        varying vec3 vCubeMaskVec;
+    #endif
+#else
+    varying vec4 vVertexLight;
+    varying vec3 vNormal;
+    #ifdef NORMALMAP
+        varying vec3 vTangent;
+        varying vec3 vBitangent;
+    #endif
+    varying vec4 vScreenPos;
+#endif
+
+void main()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    gl_Position = GetClipPos(worldPos);
+    vTexCoord = GetTexCoord(iTexCoord);
+
+    #if defined(PERPIXEL) && defined(NORMALMAP)
+        vec3 vNormal;
+        vec3 vTangent;
+        vec3 vBitangent;
+    #endif
+
+    vNormal = GetWorldNormal(modelMatrix);
+    #ifdef NORMALMAP
+        vTangent = GetWorldTangent(modelMatrix);
+        vBitangent = cross(vTangent, vNormal) * iTangent.w;
+    #endif
+    
+    #ifdef PERPIXEL
+        // Per-pixel forward lighting
+        vec4 projWorldPos = vec4(worldPos, 1.0);
+
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            for (int i = 0; i < NUMCASCADES; i++)
+                vShadowPos[i] = GetShadowPos(i, projWorldPos);
+        #endif
+
+        #ifdef SPOTLIGHT
+            // Spotlight projection: transform from world space to projector texture coordinates
+            vSpotPos = cLightMatrices[0] * projWorldPos;
+        #endif
+    
+        #ifdef POINTLIGHT
+            vCubeMaskVec = mat3(cLightMatrices[0][0].xyz, cLightMatrices[0][1].xyz, cLightMatrices[0][2].xyz) * (cLightPos.xyz - worldPos);
+        #endif
+    
+        #ifdef NORMALMAP
+            mat3 tbn = mat3(vTangent, vBitangent, vNormal);
+            #ifdef DIRLIGHT
+                vLightVec = vec4(cLightDir * tbn, GetDepth(gl_Position));
+            #else
+                vLightVec = vec4((cLightPos.xyz - worldPos) * tbn * cLightPos.w, GetDepth(gl_Position));
+            #endif
+            #ifdef SPECULAR
+                vEyeVec = (cCameraPos - worldPos) * tbn;
+            #endif
+        #else
+            #ifdef DIRLIGHT
+                vLightVec = vec4(cLightDir, GetDepth(gl_Position));
+            #else
+                vLightVec = vec4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(gl_Position));
+            #endif
+            #ifdef SPECULAR
+                vEyeVec = cCameraPos - worldPos;
+            #endif
+        #endif
+    #else
+        // Ambient & per-vertex lighting
+        vVertexLight = vec4(GetAmbient(GetZonePos(worldPos)), GetDepth(gl_Position));
+
+        #ifdef NUMVERTEXLIGHTS
+            for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
+                vVertexLight.rgb += GetVertexLight(i, worldPos, vNormal) * cVertexLights[i * 3].rgb;
+        #endif
+        
+        vScreenPos = GetScreenPos(gl_Position);
+    #endif
+}

+ 55 - 0
Bin/CoreData/Shaders/GLSL/Vegetation.xml

@@ -0,0 +1,55 @@
+<shaders>
+    <shader type="vs">
+        <option name="Normal" define="NORMALMAP" />
+        <variation name="" define="AMBIENT" />
+        <variation name="1VL" define="NUMVERTEXLIGHTS=1" />
+        <variation name="2VL" define="NUMVERTEXLIGHTS=2" />
+        <variation name="3VL" define="NUMVERTEXLIGHTS=3" />
+        <variation name="4VL" define="NUMVERTEXLIGHTS=4" />
+        <variation name="Dir">
+            <define name="DIRLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Spot">
+            <define name="SPOTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Point">
+            <define name="POINTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <option name="Spec" define="SPECULAR" require="PERPIXEL" />
+        <option name="Shadow" define="SHADOW" require="PERPIXEL" />
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+        <variation name="Billboard" define="BILLBOARD" />
+    </shader>
+    <shader type="ps">
+        <option name="Diff" define="DIFFMAP" />
+        <option name="Normal" define="NORMALMAP" require="DIFFMAP" />
+        <option name="Packed" define="PACKEDNORMAL" require="NORMALMAP" />
+        <option name="SpecMap" define="SPECMAP" require="DIFFMAP" />
+        <option name="AlphaMask" define="ALPHAMASK" require="DIFFMAP" />
+        <option name="Ambient" define="AMBIENT" require="PERPIXEL" />
+        <variation name="" define="AMBIENT" />
+        <variation name="Dir">
+            <define name="DIRLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Spot">
+            <define name="SPOTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Point">
+            <define name="POINTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Prepass" define="PREPASS" />
+        <variation name="Material" define="MATERIAL" />
+        <variation name="Deferred" define="DEFERRED" />
+        <option name="Mask" define="CUBEMASK" require="POINTLIGHT" />
+        <option name="Spec" define="SPECULAR" require="PERPIXEL" />
+        <option name="Shadow" define="SHADOW" require="PERPIXEL" />
+        <option name="LQ" define="LQSHADOW" require="SHADOW" />
+    </shader>
+</shaders>

+ 15 - 0
Bin/CoreData/Shaders/GLSL/VegetationDepth.frag

@@ -0,0 +1,15 @@
+#include "Uniforms.frag"
+#include "Samplers.frag"
+
+varying vec3 vTexCoord;
+
+void main()
+{
+    #ifdef ALPHAMASK
+        float alpha = texture2D(sDiffMap, vTexCoord.xy).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    gl_FragColor = vec4(EncodeDepth(vTexCoord.z), 1.0);
+}

+ 24 - 0
Bin/CoreData/Shaders/GLSL/VegetationDepth.vert

@@ -0,0 +1,24 @@
+#include "Uniforms.vert"
+#include "Transform.vert"
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform vec2 cWindWorldSpacing;
+
+varying vec3 vTexCoord;
+
+void main()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    gl_Position = GetClipPos(worldPos);
+    vTexCoord = vec3(GetTexCoord(iTexCoord), GetDepth(gl_Position));
+}
+

+ 9 - 0
Bin/CoreData/Shaders/GLSL/VegetationDepth.xml

@@ -0,0 +1,9 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 15 - 0
Bin/CoreData/Shaders/GLSL/VegetationShadow.frag

@@ -0,0 +1,15 @@
+#include "Uniforms.frag"
+#include "Samplers.frag"
+
+varying vec2 vTexCoord;
+
+void main()
+{
+    #ifdef ALPHAMASK
+        float alpha = texture2D(sDiffMap, vTexCoord).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    gl_FragColor = vec4(1.0);
+}

+ 24 - 0
Bin/CoreData/Shaders/GLSL/VegetationShadow.vert

@@ -0,0 +1,24 @@
+#include "Uniforms.vert"
+#include "Transform.vert"
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform vec2 cWindWorldSpacing;
+
+varying vec2 vTexCoord;
+
+void main()
+{
+    mat4 modelMatrix = iModelMatrix;
+    vec3 worldPos = GetWorldPos(modelMatrix);
+    
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    gl_Position = GetClipPos(worldPos);
+    vTexCoord = GetTexCoord(iTexCoord);
+}
+

+ 9 - 0
Bin/CoreData/Shaders/GLSL/VegetationShadow.xml

@@ -0,0 +1,9 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 282 - 0
Bin/CoreData/Shaders/HLSL/Vegetation.hlsl

@@ -0,0 +1,282 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+#include "ScreenPos.hlsl"
+#include "Lighting.hlsl"
+#include "Fog.hlsl"
+
+// With SM2 alpha-masked point light shadows become too complex, so disable specular lighting
+#if !defined(SM3) && defined(POINTLIGHT) && defined(SHADOW) && defined(ALPHAMASK)
+    #undef SPECULAR
+#endif
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform float2 cWindWorldSpacing;
+
+void VS(float4 iPos : POSITION,
+    float3 iNormal : NORMAL,
+    float2 iTexCoord : TEXCOORD0,
+    #ifdef LIGHTMAP
+        float2 iTexCoord2 : TEXCOORD1,
+    #endif
+    #ifdef NORMALMAP
+        float4 iTangent : TANGENT,
+    #endif
+    #ifdef SKINNED
+        float4 iBlendWeights : BLENDWEIGHT,
+        int4 iBlendIndices : BLENDINDICES,
+    #endif
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD2,
+    #endif
+    #ifdef BILLBOARD
+        float2 iSize : TEXCOORD1,
+    #endif
+    out float2 oTexCoord : TEXCOORD0,
+    #ifdef PERPIXEL
+        out float4 oLightVec : TEXCOORD1,
+        #ifndef NORMALMAP
+            out float3 oNormal : TEXCOORD2,
+        #endif
+        #ifdef SPECULAR
+            out float3 oEyeVec : TEXCOORD3,
+        #endif
+        #ifdef SHADOW
+            out float4 oShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
+        #ifdef SPOTLIGHT
+            out float4 oSpotPos : TEXCOORD5,
+        #endif
+        #ifdef POINTLIGHT
+            out float3 oCubeMaskVec : TEXCOORD5,
+        #endif
+    #else
+        out float4 oVertexLight : TEXCOORD1,
+        out float3 oNormal : TEXCOORD2,
+        #ifdef NORMALMAP
+            out float3 oTangent : TEXCOORD3,
+            out float3 oBitangent : TEXCOORD4,
+        #endif
+        out float4 oScreenPos : TEXCOORD5,
+    #endif
+    out float4 oPos : POSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    oPos = GetClipPos(worldPos);
+    oTexCoord = GetTexCoord(iTexCoord);
+
+    #if defined(PERPIXEL) && defined(NORMALMAP)
+        float3 oNormal;
+        float3 oTangent;
+        float3 oBitangent;
+    #endif
+
+    oNormal = GetWorldNormal(modelMatrix);
+    #ifdef NORMALMAP
+        oTangent = GetWorldTangent(modelMatrix);
+        oBitangent = cross(oTangent, oNormal) * iTangent.w;
+    #endif
+
+    #ifdef PERPIXEL
+        // Per-pixel forward lighting
+        float4 projWorldPos = float4(worldPos, 1.0);
+
+        #ifdef DIRLIGHT
+            oLightVec = float4(cLightDir, GetDepth(oPos));
+        #else
+            oLightVec = float4((cLightPos.xyz - worldPos) * cLightPos.w, GetDepth(oPos));
+        #endif
+    
+        #ifdef SHADOW
+            // Shadow projection: transform from world space to shadow space
+            GetShadowPos(projWorldPos, oShadowPos);
+        #endif
+
+        #ifdef SPOTLIGHT
+            // Spotlight projection: transform from world space to projector texture coordinates
+            oSpotPos = mul(projWorldPos, cLightMatrices[0]);
+        #endif
+
+        #ifdef POINTLIGHT
+            oCubeMaskVec = mul(oLightVec.xyz, (float3x3)cLightMatrices[0]);
+        #endif
+
+        #ifdef NORMALMAP
+            float3x3 tbn = float3x3(oTangent, oBitangent, oNormal);
+            oLightVec.xyz = mul(tbn, oLightVec.xyz);
+            #ifdef SPECULAR
+                oEyeVec = mul(tbn, cCameraPos - worldPos);
+            #endif
+        #elif defined(SPECULAR)
+            oEyeVec = cCameraPos - worldPos;
+        #endif
+    #else
+        // Ambient & per-vertex lighting
+        oVertexLight = float4(GetAmbient(GetZonePos(worldPos)), GetDepth(oPos));
+
+        #ifdef NUMVERTEXLIGHTS
+            for (int i = 0; i < NUMVERTEXLIGHTS; ++i)
+                oVertexLight.rgb += GetVertexLight(i, worldPos, oNormal) * cVertexLights[i * 3].rgb;
+        #endif
+        
+        oScreenPos = GetScreenPos(oPos);
+    #endif
+}
+
+void PS(float2 iTexCoord : TEXCOORD0,
+    #ifdef PERPIXEL
+        float4 iLightVec : TEXCOORD1,
+        #ifndef NORMALMAP
+            float3 iNormal : TEXCOORD2,
+        #endif
+        #ifdef SPECULAR
+            float3 iEyeVec : TEXCOORD3,
+        #endif
+        #ifdef SHADOW
+            float4 iShadowPos[NUMCASCADES] : TEXCOORD4,
+        #endif
+        #ifdef SPOTLIGHT
+            float4 iSpotPos : TEXCOORD5,
+        #endif
+        #ifdef CUBEMASK
+            float3 iCubeMaskVec : TEXCOORD5,
+        #endif
+    #else
+        float4 iVertexLight : TEXCOORD1,
+        float3 iNormal : TEXCOORD2,
+        #ifdef NORMALMAP
+            float3 iTangent : TEXCOORD3,
+            float3 iBitangent : TEXCOORD4,
+        #endif
+        float4 iScreenPos : TEXCOORD5,
+    #endif
+    #ifdef PREPASS
+        out float4 oDepth : COLOR1,
+    #endif
+    #ifdef DEFERRED
+        out float4 oAlbedo : COLOR1,
+        out float4 oNormal : COLOR2,
+        out float4 oDepth : COLOR3,
+    #endif
+    out float4 oColor : COLOR0)
+{
+    // Get material diffuse albedo
+    #ifdef DIFFMAP
+        float4 diffInput = tex2D(sDiffMap, iTexCoord);
+        #ifdef ALPHAMASK
+            if (diffInput.a < 0.5)
+                discard;
+        #endif
+        float4 diffColor = cMatDiffColor * diffInput;
+    #else
+        float4 diffColor = cMatDiffColor;
+    #endif
+    
+    // Get material specular albedo
+    #ifdef SPECMAP
+        float3 specColor = cMatSpecColor.rgb * tex2D(sSpecMap, iTexCoord).rgb;
+    #else
+        float3 specColor = cMatSpecColor.rgb;
+    #endif
+
+    #if defined(PERPIXEL)
+        // Per-pixel forward lighting
+        float3 lightDir;
+        float3 lightColor;
+        float3 finalColor;
+        float diff;
+
+        #ifdef NORMALMAP
+            float3 normal = DecodeNormal(tex2D(sNormalMap, iTexCoord));
+        #else
+            float3 normal = normalize(iNormal);
+        #endif
+
+        diff = GetDiffuse(normal, iLightVec.xyz, lightDir);
+
+        #ifdef SHADOW
+            diff *= GetShadow(iShadowPos, iLightVec.w);
+        #endif
+    
+        #if defined(SPOTLIGHT)
+            lightColor = iSpotPos.w > 0.0 ? tex2Dproj(sLightSpotMap, iSpotPos).rgb * cLightColor.rgb : 0.0;
+        #elif defined(CUBEMASK)
+            lightColor = texCUBE(sLightCubeMap, iCubeMaskVec).rgb * cLightColor.rgb;
+        #else
+            lightColor = cLightColor.rgb;
+        #endif
+    
+        #ifdef SPECULAR
+            float spec = GetSpecular(normal, iEyeVec, lightDir, cMatSpecColor.a);
+            finalColor = diff * lightColor * (diffColor.rgb + spec * specColor * cLightColor.a);
+        #else
+            finalColor = diff * lightColor * diffColor.rgb;
+        #endif
+    
+        #ifdef AMBIENT
+            finalColor += cAmbientColor * diffColor.rgb;
+            oColor = float4(GetFog(finalColor, iLightVec.w), diffColor.a);
+        #else
+            oColor = float4(GetLitFog(finalColor, iLightVec.w), diffColor.a);
+        #endif
+    #elif defined(PREPASS)
+        // Fill light pre-pass G-Buffer
+        #ifdef NORMALMAP
+            float3x3 tbn = float3x3(iTangent, iBitangent, iNormal);
+            float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord.xy)), tbn);
+        #else
+            float3 normal = iNormal;
+        #endif
+
+        float specPower = cMatSpecColor.a / 255.0;
+
+        oColor = float4(normal * 0.5 + 0.5, specPower);
+        oDepth = iVertexLight.a;
+    #elif defined(DEFERRED)
+        // Fill deferred G-buffer
+        #ifdef NORMALMAP
+            float3x3 tbn = float3x3(iTangent, iBitangent, iNormal);
+            float3 normal = mul(DecodeNormal(tex2D(sNormalMap, iTexCoord)), tbn);
+        #else
+            float3 normal = iNormal;
+        #endif
+
+        // If using SM2, light volume shader may not have instructions left to normalize the normal. Therefore do it here
+        #if !defined(SM3)
+            normal = normalize(normal);
+        #endif
+
+        float specIntensity = specColor.g;
+        float specPower = cMatSpecColor.a / 255.0;
+
+        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
+
+        oColor = float4(GetFog(finalColor, iVertexLight.a), 1.0);
+        oAlbedo = GetFogFactor(iVertexLight.a) * float4(diffColor.rgb, specIntensity);
+        oNormal = float4(normal * 0.5 + 0.5, specPower);
+        oDepth = iVertexLight.a;
+    #else
+        // Ambient & per-vertex lighting
+        float3 finalColor = iVertexLight.rgb * diffColor.rgb;
+
+        #ifdef MATERIAL
+            // Add light pre-pass accumulation result
+            // Lights are accumulated at half intensity. Bring back to full intensity now
+            float4 lightInput = 2.0 * tex2Dproj(sLightBuffer, iScreenPos);
+            float3 lightSpecColor = lightInput.a * (lightInput.rgb / GetIntensity(lightInput.rgb));
+
+            finalColor += lightInput.rgb * diffColor.rgb + lightSpecColor * specColor;
+        #endif
+
+        oColor = float4(GetFog(finalColor, iVertexLight.a), diffColor.a);
+    #endif
+}

+ 56 - 0
Bin/CoreData/Shaders/HLSL/Vegetation.xml

@@ -0,0 +1,56 @@
+<shaders>
+    <shader type="vs">
+        <option name="Normal" define="NORMALMAP" />
+        <variation name="" define="AMBIENT" />
+        <variation name="1VL" define="NUMVERTEXLIGHTS=1" />
+        <variation name="2VL" define="NUMVERTEXLIGHTS=2" />
+        <variation name="3VL" define="NUMVERTEXLIGHTS=3" />
+        <variation name="4VL" define="NUMVERTEXLIGHTS=4" />
+        <variation name="Dir">
+            <define name="DIRLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Spot">
+            <define name="SPOTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Point">
+            <define name="POINTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <option name="Spec" define="SPECULAR" require="PERPIXEL" />
+        <option name="Shadow" define="SHADOW" require="PERPIXEL" />
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+        <variation name="Instanced" define="INSTANCED" require="SM3" />
+        <variation name="Billboard" define="BILLBOARD" />
+    </shader>
+    <shader type="ps">
+        <option name="Diff" define="DIFFMAP" />
+        <option name="Normal" define="NORMALMAP" require="DIFFMAP" />
+        <option name="Packed" define="PACKEDNORMAL" require="NORMALMAP" />
+        <option name="AlphaMask" define="ALPHAMASK" require="DIFFMAP" />
+        <option name="Ambient" define="AMBIENT" require="PERPIXEL" />
+        <variation name="" define="AMBIENT" />
+        <variation name="Dir">
+            <define name="DIRLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Spot">
+            <define name="SPOTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Point">
+            <define name="POINTLIGHT" />
+            <define name="PERPIXEL" />
+        </variation>
+        <variation name="Prepass" define="PREPASS" />
+        <variation name="Material" define="MATERIAL" />
+        <variation name="Deferred" define="DEFERRED" />
+        <option name="Mask" define="CUBEMASK" require="POINTLIGHT" />
+        <option name="Spec" define="SPECULAR" require="PERPIXEL" />
+        <option name="Shadow" define="SHADOW" require="PERPIXEL" />
+        <option name="LQ" define="LQSHADOW" require="HWSHADOW" />
+        <option name="HW" define="HWSHADOW" require="SHADOW" />
+    </shader>
+</shaders>

+ 45 - 0
Bin/CoreData/Shaders/HLSL/VegetationDepth.hlsl

@@ -0,0 +1,45 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform float2 cWindWorldSpacing;
+
+void VS(float4 iPos : POSITION,
+    #ifdef SKINNED
+        float4 iBlendWeights : BLENDWEIGHT,
+        int4 iBlendIndices : BLENDINDICES,
+    #endif
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD2,
+    #endif
+    float2 iTexCoord : TEXCOORD0,
+    out float3 oTexCoord : TEXCOORD0,
+    out float4 oPos : POSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    oPos = GetClipPos(worldPos);
+    oTexCoord = float3(GetTexCoord(iTexCoord), GetDepth(oPos));
+}
+
+void PS(
+    float3 iTexCoord : TEXCOORD0,
+    out float4 oColor : COLOR0)
+{
+    #ifdef ALPHAMASK
+        float alpha = tex2D(sDiffMap, iTexCoord.xy).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    oColor = iTexCoord.z;
+}

+ 10 - 0
Bin/CoreData/Shaders/HLSL/VegetationDepth.xml

@@ -0,0 +1,10 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+        <variation name="Instanced" define="INSTANCED" require="SM3" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 45 - 0
Bin/CoreData/Shaders/HLSL/VegetationShadow.hlsl

@@ -0,0 +1,45 @@
+#include "Uniforms.hlsl"
+#include "Samplers.hlsl"
+#include "Transform.hlsl"
+
+uniform float cWindHeightFactor;
+uniform float cWindHeightPivot;
+uniform float cWindPeriod;
+uniform float2 cWindWorldSpacing;
+
+void VS(float4 iPos : POSITION,
+    #ifdef SKINNED
+        float4 iBlendWeights : BLENDWEIGHT,
+        int4 iBlendIndices : BLENDINDICES,
+    #endif
+    #ifdef INSTANCED
+        float4x3 iModelInstance : TEXCOORD2,
+    #endif
+    float2 iTexCoord : TEXCOORD0,
+    out float2 oTexCoord : TEXCOORD0,
+    out float4 oPos : POSITION)
+{
+    float4x3 modelMatrix = iModelMatrix;
+    float3 worldPos = GetWorldPos(modelMatrix);
+
+    float windStrength = max(iPos.y - cWindHeightPivot, 0.0) * cWindHeightFactor;
+    float windPeriod = cElapsedTime * cWindPeriod + dot(worldPos.xz, cWindWorldSpacing);
+    worldPos.x += windStrength * sin(windPeriod);
+    worldPos.z -= windStrength * cos(windPeriod);
+
+    oPos = GetClipPos(worldPos);
+    oTexCoord = GetTexCoord(iTexCoord);
+}
+
+void PS(
+    float2 iTexCoord : TEXCOORD0,
+    out float4 oColor : COLOR0)
+{
+    #ifdef ALPHAMASK
+        float alpha = tex2D(sDiffMap, iTexCoord).a;
+        if (alpha < 0.5)
+            discard;
+    #endif
+
+    oColor = 1.0;
+}

+ 10 - 0
Bin/CoreData/Shaders/HLSL/VegetationShadow.xml

@@ -0,0 +1,10 @@
+<shaders>
+    <shader type="vs">
+        <variation name="" />
+        <variation name="Skinned" define="SKINNED" />
+        <variation name="Instanced" define="INSTANCED" require="SM3" />
+    </shader>
+    <shader type="ps">
+        <option name="AlphaMask" define="ALPHAMASK" />
+    </shader>
+</shaders>

+ 10 - 0
Bin/CoreData/Techniques/VegetationDiff.xml

@@ -0,0 +1,10 @@
+<technique>
+    <pass name="base" vs="Vegetation" ps="Vegetation_Diff" />
+    <pass name="litbase" vs="Vegetation" ps="Vegetation_DiffAmbient" />
+    <pass name="light" vs="Vegetation" ps="Vegetation_Diff" depthtest="equal" depthwrite="false" blend="add" />
+    <pass name="prepass" vs="Vegetation" ps="Vegetation_DiffPrepass" />
+    <pass name="material" vs="Vegetation" ps="Vegetation_DiffMaterial" depthtest="equal" depthwrite="false" />
+    <pass name="deferred" vs="Vegetation" ps="Vegetation_DiffDeferred" />
+    <pass name="depth" vs="VegetationDepth" ps="VegetationDepth" />
+    <pass name="shadow" vs="VegetationShadow" ps="VegetationShadow" />
+</technique>

+ 10 - 0
Bin/CoreData/Techniques/VegetationDiffAlphaMask.xml

@@ -0,0 +1,10 @@
+<technique>
+    <pass name="base" vs="Vegetation" ps="Vegetation_DiffAlphaMask" alphamask="true" />
+    <pass name="litbase" vs="Vegetation" ps="Vegetation_DiffAlphaMaskAmbient" alphamask="true" />
+    <pass name="light" vs="Vegetation" ps="Vegetation_DiffAlphaMask"  depthtest="equal" depthwrite="false" blend="add" alphamask="true" />
+    <pass name="prepass" vs="Vegetation" ps="Vegetation_DiffAlphaMaskPrepass" alphamask="true" />
+    <pass name="material" vs="Vegetation" ps="Vegetation_DiffAlphaMaskMaterial" depthtest="equal" depthwrite="false" alphamask="true" />
+    <pass name="deferred" vs="Vegetation" ps="Vegetation_DiffAlphaMaskDeferred" alphamask="true" />
+    <pass name="depth" vs="VegetationDepth" ps="VegetationDepth_AlphaMask" alphamask="true" />
+    <pass name="shadow" vs="VegetationShadow" ps="VegetationShadow_AlphaMask" alphamask="true" />
+</technique>

+ 9 - 0
Bin/Data/Materials/MushroomWind.xml

@@ -0,0 +1,9 @@
+<material>
+    <technique name="Techniques/VegetationDiff.xml" />
+    <texture unit="diffuse" name="Textures/Mushroom.dds" />
+    <parameter name="MatSpecColor" value="0.1 0.1 0.1 16" />
+    <parameter name="WindPeriod" value="1" />
+    <parameter name="WindHeightFactor" value="0.2" />
+    <parameter name="WindHeightPivot" value="0.2" />
+    <parameter name="WindWorldSpacing" value="0.1 0.1" />
+</material>