So I've been delving into "Texturing & Modeling: A Procedural Approach" recently and started writing my first procedural textures in GLSL. What gives me the most headaches though is the topic of antialiasing. It's obvious how to do it in simple cases like very regular patterns (analytical averaging using integration) or spectral synthesis (frequency clamping), but whenever it's something else, none of the methods seem to work.
I have the following code which is just one part of a procedural wood (tree) texture:
vec4 TreeTexCompute(in vec2 sp)
{
const float holeFrequency = 1.0;
const vec2 holeThreshold = vec2(0.6, 0.85);
vec2 vfw = fwidth(sp);
float fw = max(vfw.x, vfw.y);
float holeNyquist = 0.5 * holeFrequency * (1.0 / fw);
// Upper bound for the frequencies in the function to compute 'hole' below
float holeHighestFreq = 1.0 / (0.5 * (holeThreshold.y-holeThreshold.x));
// Spawn a hole where gnoise has its "maximum" values
float hole = smoothstep(holeThreshold.x, holeThreshold.y, gnoise(vec3(sp*holeFrequency, -3.75))*0.5 + 0.5);
// Gradually fade out the hole as we approach the nyquist frequency
float t = mix(hole, 0.0, smoothstep(0.5*holeNyquist, holeNyquist, holeHighestFreq));
return vec4(t, t, t, 1.0);
}
What it does is randomly place small "holes" by feeding the output of a Perlin-style gradient noise (float gnoise(vec3)
) into the smoothstep
function, creating light spots only around the maximum values of gnoise
.
Antialiasing is done by gradually fading this value out to black as we approach the nyquist frequency. However, it seems that the fadeout happens WAY too early. The camera basically has to touch the texture surface to see any holes at all. This doesn't seem right and when I disable the fadeout I can't see any aliasing until I'm much farther away.
So what am I doing wrong? I thought about my frequency calculations for a while and can't find anything wrong with them. The nyquist frequency is half the sample rate, and the highest frequency (an upper bound, really) of the function used to compute 'hole' results from the maximum frequency of gnoise
(which I believe is about 2.0) and smoothstep
(which if I understand correctly is approximately the inverse of its ramp width).
And by the way: What would you say is the preferred way to antialias such a texture of randomly placed holes? Fading them out entirely is the only thing I could think of, but it doesn't seem very satisfying. Supersampling I assume is just a hack and doesn't really solve the problem. I'm using similar techniques of feeding streched gradient noise to smoothstep
functions to generate many other features of the wood texture, including larger fissures, so I really need good antialiasing for this.