I'm trying to develop a real time rendering method using real time acquired envmap (cubemap) for lightning.

This implies that my envmap can change as often as every frame and I therefore cannot use any method base on precomputation of the envmap (such as convolution with BRDF...)

So far my method worked well with Phong BRDF. For specular contribution I direclty read the value in my sampleCube and I use mipmap levels + linear filter for simulating the roughtness of the material considered:

int size                = textureSize(envmap, 0).x;
float specular_level    = log2(size * sqrt(3.0)) - 0.5 * log2(ns + 1);
vec3 env_specular       = ks * specular_color * textureLod(envmap, l_g, specular_level);

From this method I would like to upgrade to a microfacet based BRDF. I already have algorithm for evaluating the shape (including anisotropic direction) of the reflection but I cannot manage to read the values I want in my sampleCube.

I believe I have to use

textureGrad(envmap, l_g, X, Y);

with l_g being the reflection direction in global space but I cannot manage to find which values to give to X and Y in order to correctly specify the area I want to consider.

What value should I give to X and Y in orther for

textureGrad(envmap, l_g, X, Y);

to give the same result as

textureLod(envmap, l_g, specular_level);
  • \$\begingroup\$ I thinked a convolution in compute shader a relatively cheap, there possible use stohastic sampling also. \$\endgroup\$ Jan 13, 2015 at 5:30

1 Answer 1


The gradient values are normally (when you do a standard texture lookup) the screen-space derivatives of the texture coordinates, dFdx(l_g), dFdy(l_g).

In order to do anisotropic filtering while also specifying the base mip level as specularLevel, you could try rescaling the derivatives so the length of the smaller derivative is pow(2.0, specularLevel). You want to maintain the relationship between the two derivatives so that the aniso filter has the same shape. Something like this:

vec3 derivX = dFdx(l_g);
vec3 derivY = dFdy(l_g);
float minLength = sqrt(min(dot(derivX, derivX), dot(derivY, derivY)));
float desiredLength = pow(2.0, specularLevel);
float scale = desiredLength / minLength;
derivX *= scale;
derivY *= scale;
... textureGrad(envmap, l_g, derivX, derivY);
  • \$\begingroup\$ I tried rescaling those simple derivative (basically i'll, at some point, have to rotate derivX and derivY for chossing the right anysotropic dirrection). Strangly enough I don't get the same result using textureGrad(envmap, l_g, derivX, derivY); and textureLod(envmap, l_g, specular_level); I would say that the scaling factor looks way over what it would need to be. Here are screenshots textureLod textureGrad \$\endgroup\$
    – Amxx
    Apr 30, 2014 at 12:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .