Directional Light Normal Specular Map + Parallax Mapping

👉 BlitzCoder will be building a new platform and other plans to preserve and continue the Blitz legacy.

To be able to achieve this goal, we need your support by becoming a Patreon Paid Member 👈


Tweet blitzmax glsl shaders code-archives openb3d

This is one of those wip shaders that is now part of my lost archives.

One of the defacto shaders, particularly if you are making outdoor scenes and games.

Updated with source below

Directional Light Normal + Specular Mapping

Directional Light Parallax Mapping


Local colortex:TTexture=LoadTexture("../media/diffuse.tga")
Local normaltex:TTexture=LoadTexture("../media/normal.tga")
Local disptex:TTexture=LoadTexture("../media2/heightmap.tga") ' displacement or heightmap
Local spectex:TTexture=LoadTexture("../media2/specular.png")

Local shader:TShader=LoadShader("","../glsl/normal-parallax.vert.glsl","../glsl/normal-parallax.frag.glsl")

SetFloat(shader, "scale", 0.08) '0.08
SetFloat(shader, "bias", -0.06) '-0.06
SetInteger(shader, "parallax", 0)  ' set to 1 for parallax effect


varying vec3 lightDir;
varying vec3 halfVector;

uniform vec3 vTangent;

void main()
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;

    vec3 n = normalize(gl_NormalMatrix * gl_Normal);
    vec3 t = normalize(gl_NormalMatrix * vTangent);
    vec3 b = cross(n, t) * gl_MultiTexCoord1.w;

    mat3 tbnMatrix = mat3(t.x, b.x, n.x,
                          t.y, b.y, n.y,
                          t.z, b.z, n.z);

    lightDir = gl_LightSource[0];
    lightDir = tbnMatrix * lightDir;

    halfVector = gl_LightSource[0];
    halfVector = tbnMatrix * halfVector;


uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform sampler2D heightMap;

uniform sampler2D specMap;

uniform int parallax;

uniform float scale;
uniform float bias; 

varying vec3 lightDir;
varying vec3 halfVector;

uniform float density;
uniform vec4 fogColor;

void main()
    vec2 newTexCoord;
    vec3 h = normalize(halfVector);

    if (parallax > 0)
        float height = texture2D(heightMap, gl_TexCoord[0].st).r;

        height = height * scale + bias;
        newTexCoord = gl_TexCoord[0].st + (height * h.xy);
        newTexCoord = gl_TexCoord[0].st;

    vec3 n = normalize(texture2D(normalMap, newTexCoord).rgb * 2.0 - 1.0);
    vec3 l = normalize(lightDir);

    float nDotL = max(0.0, dot(n, l));
    float nDotH = max(0.0, dot(n, h));
    float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);

    vec4 ambient = gl_LightSource[0].ambient * gl_FrontMaterial.ambient;    
    vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;

    //vec4 specular = gl_FrontLightProduct[0].specular * power; // use this for default specular highlights and without using specular map
    vec4 specular = texture2D(specMap, newTexCoord).r * power;

    vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;

    gl_FragColor = color * texture2D(colorMap, newTexCoord);

    // calculate 2nd order exponential fog factor based on fragment's Z distance
    const float e = 2.71828;
    float fogFactor = (density * gl_FragCoord.z);
    fogFactor *= fogFactor;
    fogFactor = clamp(pow(e, -fogFactor), 0.0, 1.0);

    vec4 finalColor = color * texture2D(colorMap, newTexCoord);
    gl_FragColor = mix(fogColor, finalColor, fogFactor);    
markcwm commented:

Hi Ron,

this looks great, I prefer the parallax mapping although they do look very similar.

What's the difference between specular mapping and bump mapping?


BlitzCoder commented:

Thanks Mark! Yes, with paralllax mapping it adds more depth and detail but sometimes the effect exaggerates it.

Specular mapping is obviously an old technique where you just control and map shininess with it's own texture map, although getting it from normal map technically counts, where bump mapping is another old technique similar to normal mapping.

I think you already got this covered with bumpmap examples, but it seems there is an issue with directional lighting mode where objects gets darker when the camera is from a distance. This shader solves it but the spotlight and pointlight is not included (yet).

BlitzCoder commented:

Hey Mark, finally.. just found the code in my archives it's straightforward material shader so it should work on your latest version.

There are also options for default specular highlights (w/o specular mapping) and mixing with the fog component, but this one not fully tested though.

markcwm commented:

Hi Ron,

that's cool thanks, I look forward to trying it out. Yes, I can see the code for default specular and fog mixing. Will test those out too.

BlitzCoder commented:

cheers. I just remembered angros47 also did a normal mapping shader one which I created a preview in BlitzX HTML5 target somewhere here on the site. I forgot though if it has the same directional lighting setup and it's embedded in OpenB3D Plus sources.

Reply To Topic (minimum 10 characters)

Please log in to reply