Barabas' Parallax Mapping
Barabas implemented Parallax Mapping in Mount&Blade, for this to work you need to specify the height in the red channel of your normal map. Everything is configurable. Please note that every GPU instruction counts and it's always better a good performance than amazing visuals.
Use it wisely.
Pixel Shader:
PS_OUTPUT ps_main_bump( VS_OUTPUT_BUMP In, uniform const int PcfMode ,uniform const bool use_parallax = false, uniform const bool use_self_shading = false) { PS_OUTPUT Output; float3 normal; Output.RGBColor.rgb =1.0f; float shade; if(use_parallax) { float height = (tex2D(NormalTextureSampler, In.Tex0).r); float fHeightMapScale = 0.015; float heightmap = .5f-height; In.Tex0 -= fHeightMapScale *heightmap * In.ViewDir.xy*In.WorldNormal.w; normal.xy = (2.0f * tex2D(NormalTextureSampler, In.Tex0).ag - 1.0f); normal.z = sqrt(1.0f - dot(normal.xy, normal.xy)); shade = saturate(dot(In.SunLightDir.xyz, normal.xyz)); if (In.SunLightDir.z > 0.0 && use_self_shading) { float height2 = tex2D(NormalTextureSampler, In.Tex0 + (fHeightMapScale *heightmap * In.SunLightDir.xy)/max(0.2,In.SunLightDir.z) ).r; Output.RGBColor.rgb -= 0.7*saturate(height2-height); } } else { normal.xy = (2.0f * tex2D(NormalTextureSampler, In.Tex0).ag - 1.0f); normal.z = sqrt(1.0f - dot(normal.xy, normal.xy)); shade = saturate(dot(In.SunLightDir.xyz, normal.xyz)); } float4 total_light = vAmbientColor;//In.LightAmbient; if (PcfMode != PCF_NONE) { float sun_amount = 0.03f + GetSunAmount(PcfMode, In.ShadowTexCoord, In.ShadowTexelPos); total_light += shade * sun_amount * vSunColor; } else { total_light += shade * vSunColor; } total_light += saturate(dot(In.SkyLightDir.xyz, normal.xyz)) * vSkyLightColor; #ifndef USE_LIGHTING_PASS total_light += saturate(dot(In.PointLightDir.xyz, normal.xyz)) * vPointLightColor; #endif Output.RGBColor.rgb *= total_light.rgb; Output.RGBColor.a = 1.0f; Output.RGBColor *= vMaterialColor; float4 tex_col = tex2D(MeshTextureSampler, In.Tex0); INPUT_TEX_GAMMA(tex_col.rgb); Output.RGBColor *= tex_col; //turned off texture map for testing shadow Output.RGBColor *= In.VertexColor; OUTPUT_GAMMA(Output.RGBColor.rgb); return Output; }
[edit] Source
Latest (optimized) version: http://forums.taleworlds.com/index.php/topic,208694.msg5072033.html#msg5072033
Massive loop (slow) version: http://forums.taleworlds.com/index.php/topic,208694.msg5071585.html#msg5071585 and
Original implementation: http://forums.taleworlds.com/index.php/topic,208694.msg5069190.html#msg5069190
[edit] Preview
A good bunch of screenshots can be found here: http://forums.taleworlds.com/index.php/topic,208694.msg5126320.html#msg5126320