Perturb a normal in the fragment shader using a normal map. This can be used to add surface detail during per-pixel lighting.
Note: You need to enable GL_OES_standard_derivatives
.
#extension GL_OES_standard_derivatives : enable
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 vViewPosition;
uniform sampler2D normalMap;
#pragma glslify: perturb = require('glsl-perturb-normal')
void main() {
//extract normal map from your texture
vec3 normalRGB = texture2D(normalMap, vUv).rgb;
//expand into -1.0 .. 1.0 range
vec3 normalMap = normalRGB * 2.0 - 1.0;
//get surface normal and camera-space position
vec3 N = normalize(vNormal);
vec3 V = normalize(vViewPosition);
//perturb the normal
vec3 normal = perturb(normalMap, N, V, vUv);
//... lighting
}
Perturbs a normal where:
M
is a unit vector from your normal map (e.g. decoded from a RGB texture)N
is the normalized surface normalV
is the normalized camera-space positiontexcoord
is the UV coordinates of your mesh
This uses GL_OES_standard_derivatives
to compute the derivatives, so it may not work on older or low-end devices.
The algorithm here is from Christian Schüler's blog post Normal Mapping Without Precomputed Tangents.
MIT. See LICENSE.md for details.