0
\$\begingroup\$

So I understand that for best results one uses a height (or bump) map and a normal map together.

And I also understand that one can calculate a normal map from a height map using some sobel operator.

But out of curiosity I wonder how the first games that supported bump mapping did it.

I found this fragment shader code that seems to do it, but I am not sure: OpenGL Bump Map -- Texture artifacts ?

If the code above does exactly what I am looking for, can someone explain the line

vec3 normalDirection = normalize(tangenteSpace*(texture2D( bump_tex, f_texcoord ).rgb*2.0 - 1.0));

How can you get a normal from a bump ?
I understand what tangent space is mathematically but how does it work here ?
Is it a vec4 or a matrix ?

So basically my question is: How was bump mapping done without a normal map in the old days ?

\$\endgroup\$
  • \$\begingroup\$ The line you quoted is reading a normal map. Not a bump map. \$\endgroup\$ – user253751 Aug 15 at 4:50
1
\$\begingroup\$

Bump mapping simulates surface displacement, i.e. the shader pretends that the pixel is further back along the surface normal than it actually is. It then compares the depth to the pixels next to it on the map, and so can establish a gradient, using pythagoras: if we know the difference in height, and the difference in pixels to the left/right/up/down/etc, then we can compute the slope in each direction. We can then use those slopes to calculate a new normal vector for that pixel. This involves several texture samples per pixel, in the sobel matrix you mentioned, and is indeed how it was done "back in the day".

For this reason, it is expensive, and sub-optimal, and in the case of blurred height maps, can led to artifacts like the ones you saw.

Normal mapping on the other hand, uses a normal map, pre-baked from a bump, or displacement ma, in exactly the same method as above. The difference is, that by doing it in advance, you save on at least 4-8 texture samples per pixel, in addition to not having to compute the slopes per pixel. Not having to do this FAR outweighs the cost of the matrix transformations from tangent to view space per pixel, making lighting much more efficient. This is how it is done in today's hardware, though tomorrow's graphics engine will likely use raytracing instead.

\$\endgroup\$
  • \$\begingroup\$ Very interesting! Are you able to explain the line of code that I posted above ? I don't see any other texture lookups or sobel operations in the code from the link either. \$\endgroup\$ – Ray Hulha Aug 14 at 14:37
  • \$\begingroup\$ That line of code is nothing more than transforming the sampled colour out of tangent space and into view space. I recommend reading learnopengl.com/Advanced-Lighting/Normal-Mapping for a better explanation. \$\endgroup\$ – Ian Young Aug 14 at 17:50
  • \$\begingroup\$ But my point is, as far as I can tell, that the line of code does not come from a shader using normal mapping. Then it would be easy. The line of code comes from a shader using a bump/height map. That is the hard to understand part... \$\endgroup\$ – Ray Hulha Aug 14 at 19:57
  • \$\begingroup\$ Put simply, the person who wrote that code, should be sampling a normal map, not a bump map. The wrong texture is being used. I would recommend you use a normal map too. It's superior in every regard, and is an industry standard technique. \$\endgroup\$ – Ian Young Aug 14 at 23:04
  • \$\begingroup\$ I have actually added an answer to the question you linked as well, which should help both you and the OP \$\endgroup\$ – Ian Young Aug 14 at 23:17
0
\$\begingroup\$

I found some code that seems to solve this in three.js:

https://github.com/mrdoob/three.js/blob/dev/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js

    vec2 dSTdx = dFdx( vUv );
    vec2 dSTdy = dFdy( vUv );
    float Hll = bumpScale * texture2D( bumpMap, vUv ).x;
    float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;
    float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;
    return vec2( dBx, dBy );

The code is based on this whitepaper: "Bump Mapping Unparametrized Surfaces on the GPU" by Morten S. Mikkelsen

http://jbit.net/~sparky/sfgrad_bump/mm_sfgrad_bump.pdf

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.