• Welcome to the forums on our new hosting setup. Everything should be working the same, but if you run into any problems, please let us know over here.

B Tutorial Shader Ghosts and Shaders

Users who are viewing this thread


Tutorial as Word file

Needed data:
Warsword Ghost Pack

Additional readings:

How to add custom shaders to the Warsword Conquest Module:
There are two files in the root mount and blade warband folder called mb_2a.fxo and mb_2b.fxo, these are the main compiled shader files. We must add our own mb_2a.fxo and mb_2b.fxo to the warsword conquest root folder in order to load our version of the shaders. Like this:
To do this you must first compile mb.fx. Extract the ghost pack to a suitable location. In the ghost pack in the shader folder you will find the precompiled shaders

Mb.fx is the precompiled main shader, it's in text so you can read and edit it. mb_2a.fxo and mb_2b.fxo are compiled as binary making them hard to edit.

Run compile_fx.bat. This will take a little while. If there are no errors it will create mb_2a.fxo and mb_2b.fxo in the shader folder.
Copy only mb_2a.fxo and mb_2b.fxo to the warsword conquest root folder. That’s it for custom shaders: now how to use them in openbrf.

How to edit the ghosts to use the new shaders:
Copy the transparent textures from ghost pack to warsword conquest/textures.
(They are semi transparent textures saved as DXT5 (smooth alpha) dds)

(I included zombies.brf in the pack it has all the right settings for reference)

The rest of the setup is done in open brf:

Creating the shader in a brf (zombies.brf makes sense).
Settings for shader:
Requires 4000 makes the ghost shader work only for people running mount and blade on high settings.
Fallback tex_mul_color_alpha is a diffuse shader with alpha enabled.

Setting up the material correctly:
That's it! hopefully they work in-game!

Making changes to a hlsl shader:
The following is an quick guide on editing the ghost shader. It is additional information for anyone who’s interested.

Open mb.fx from the ghost pack with notepad or a text editor. This wall of text is the precompiled warband shaders.
They are hlsl shaders written for shader model 2. Scroll to the very bottom of the document.
The ghost shader begins at
//Burspa's Ghost Shader
and ends at
////Burspa Ghost Shader End
The ghost shader is a modified diffuse shader with fresnel applied. A simplified explanation of fresnel is that it finds the edges of an object. A simplified explanation of the shader is that it finds the edges of the ghost mesh, the size of these edges is based on GlowExpon, and combines the color of these edges (based on the texture assigned), with GlowColor.

There are only 2 lines of code that should be changed to alter the ghost shader.
float3 GlowColor = {244.0f, 78.0f, 66.0f};
float GlowExpon = 1.3f;

Glow Color is an rgb float
You can find rgb color values here
So let's say we wanted to make the ghosts green. Change the code from
float3 GlowColor = {244.0f, 78.0f, 66.0f};
float3 GlowColor = {70.0f, 247.0f, 64.0f};

Rgb values must have .0f on the end because they are being stored as a float.

GlowExpon is the inverse size of the edges so:
GlowExpon = 0.3f would mean the edges would be huge and almost the entire ghost would be coloured in.
GlowExpon = 6.0f would create small edges and would create a nice rim lighting effect that fresnel is usually known for.

If you make any changes to mb.fx you will need to recompile as per instructions at the beginning.

Thats all there is to changing the ghost shader.

A tip for altering shaders for Mount & Blade:
Copy all the data from the ghost pack /shader folder to mount and warband root folder (make sure you make backups of the files you replace). Make sure the module you’re using does not contain custom shader files. Now make changes to mb.fx directly from the root warband folder. And when you compile now the compiled files will be in the correct location. Now open warband in edit mode. Find the unit you are changing in edit mode. With warband still open, make changes to the mb.fx file save and recompile. Now in warband edit mode, press ctrl + f, and the shaders will be updated in game. This allows you to quickly make alterations to shaders for testing ingame without having to restart warband.

mb.fx file
Since the shader doesn't include skinning deformations inside the VS, if it's used on a skeletal mesh it will apply the deformations via CPU which is pretty inefficient.
    float4 Pos                    : POSITION;
    float4 Color                : COLOR0;
    float2 Tex0                    : TEXCOORD0;
    float  Fog                    : FOG;
    float3 ViewDir                : TEXCOORD6;
    float3 WorldNormal            : TEXCOORD7;   

VS_OUTPUT_GHOST_SHADER vs_ghost(uniform const bool use_skinning, float4 vPosition : POSITION, float4 vNormal : NORMAL, float2 tc : TEXCOORD0, float4 vColor : COLOR0, float4 vLightColor : COLOR1, float4 vBlendWeights : BLENDWEIGHT, float4 vBlendIndices : BLENDINDICES)


    float4 vObjectPos = vPosition;
    float4 vObjectN = vNormal;
        vObjectPos = skinning_deform(vPosition, vBlendWeights, vBlendIndices);
        vObjectN = normalize(skinning_deform(vNormal, vBlendWeights, vBlendIndices));

    Out.Pos = mul(matWorldViewProj, vObjectPos);

    float4 vWorldPos = (float4)mul(matWorld, vObjectPos);
    float3 vWorldN = normalize(mul((float3x3)matWorld, vObjectN)); //normal in world space
    float3 P = mul(matWorldView, vObjectPos); //position in view space

    Out.Tex0 = tc;

    float4 diffuse_light = vAmbientColor + vLightColor;
    diffuse_light += saturate(dot(vWorldN, -vSkyLightDir)) * vSkyLightColor;
    diffuse_light += saturate(dot(vWorldN, -vSunDir)) * vSunColor;
    Out.Color = (vMaterialColor * vColor * diffuse_light);

    //apply fog
    float d = length(P);
    Out.ViewDir =normalize(vCameraPos-vWorldPos);
    Out.WorldNormal = vWorldN;   

    Out.Fog = get_fog_amount_new(d, vWorldPos.z);
    return Out;

    PS_OUTPUT Output;

    float3 GlowColor = {66.0f,128.0f,130.0f};
    float GlowExpon = 1.3f;

    float4 tex_col = tex2D(MeshTextureSampler, In.Tex0);

    Output.RGBColor =  In.Color * tex_col;

    //add fresnel term
    float fresnel = 1.0-(dot( normalize(In.ViewDir), normalize(In.WorldNormal)));

    fresnel = pow(fresnel,GlowExpon);
    //fresnel = fresnel* GlowColor.rgb;
     float3 result = fresnel * GlowColor.rgb;
    Output.RGBColor.rgb *= result;

    return Output;

technique ghost_shader
    pass P0
        VertexShader = compile vs_2_0 vs_ghost(false);
        PixelShader = compile ps_2_0 ps_ghost();

technique ghost_shader_skin
    pass P0
        VertexShader = compile vs_2_0 vs_ghost(true);
        PixelShader = compile ps_2_0 ps_ghost();
Top Bottom