I am trying to implement the Ashikhmin-Shirley model using these formulas:

enter image description here

This is the GLSL 1.2 fragment shader code:

uniform vec4 materialAmbient, materialDiffuse, materialSpecular;
uniform float materialShininess;
uniform vec4 lightAmbient, lightDiffuse, lightSpecular, lightPosition;

varying vec3 P,N;

float pi= 3.1415926535;

vec4 Fd(float NdotV, float NdotL) {
    vec4 fd= (28.0 * materialDiffuse * lightDiffuse) / (23.0 * pi) * (1.0 - materialSpecular * lightSpecular);
    fd*= 1.0 - pow(1.0-NdotV/2.0,5.0);
    fd*= 1.0 - pow(1.0-NdotL/2.0, 5.0);
    return fd;

vec4 Fr(float u, vec4 specular) {
    return specular + (1.0-specular) * pow(1.0 - u, 5.0);

// f= phi
vec4 Fs(float VdotH, float NdotH, float NdotL, float NdotV, float et, float eb, float f) {
    vec4 fs= Fr(VdotH, materialSpecular * lightSpecular);
    fs*= sqrt((et+1.0) * (eb+1.0)) / (8.0 * pi);
    fs*=  pow(NdotH, et*pow(cos(f),2.0) + eb*pow(sin(f),2.0)) / (VdotH * max(NdotL, NdotV));
    return fs;

void main(void) {
    vec3 L= normalize(vec3(lightPosition) - P);
    vec3 V= cameraPosition;
    vec3 H= normalize(L+V);
    float NdotL= max(dot(N,L),0.0);
    float NdotV= max(dot(N,V),0.0);
    float NdotH= max(dot(N,H),0.0);
    float VdotH= max(dot(V,H),0.0);
    gl_FragColor= Fd(NdotV, NdotL) + Fs(VdotH, NdotH, NdotL, NdotV, 128.0,128.0,1.0);

I already checked and it seems like all the uniforms and varying are passed in the right way, I pass P and N from the vertex shader. The variables are:

  1. Light direction: L;
  2. Surface normal: N;
  3. Camera direction: V;
  4. Half vector: H;
  5. Fragment position: P.

The uniforms I pass are:

  1. light{Specular | Diffuse | Ambient} : 0xffffff (converted to a rgba vector of course);
  2. materialAmbient: 0x543807 ;
  3. materialDiffuse: 0xc6901d;
  4. materialSpecular: 0xfdefce;
  5. materialShininess: 27.8974.

This is the result I get:

enter image description here

Which seems very strange to me, I've seen other images of Ashkhmin-Shirley implementations on the web, and they aren't similar. This is an example:

enter image description here

I want one like this !! Maybe I am using wrong values of phi and other values? Or there's something wrong in the formula?

  • 1
    \$\begingroup\$ can you provide a simpler shape in your test image, like a sphere or teapot? as it's hard to judge from this. \$\endgroup\$
    – concept3d
    Nov 25 '13 at 14:23
  • 1
    \$\begingroup\$ sorry I'm feeling too lazy to look your code over, but here is my tested implementation in use in my engine: szifler.com/gdsegj/ashikhmin_shirley.glsl \$\endgroup\$
    – MickLH
    Nov 25 '13 at 14:41
  • \$\begingroup\$ @concept3d Ok, I replaced the image, there's a teapot now. \$\endgroup\$ Nov 25 '13 at 14:43
  • \$\begingroup\$ it gives you vec2(diffuse, specular), multiply by your diffuse texture sample and light color... add the specular before or after depending on if your renderer supports separate specular color \$\endgroup\$
    – MickLH
    Nov 25 '13 at 14:48
  • 5
    \$\begingroup\$ also it looks like you are using "flat" normals instead of "smooth" ones, you most likely want to research normal smoothing and pre-calculate this in your models vertices to get rid of the square artifacts no matter what lighting model you use \$\endgroup\$
    – MickLH
    Nov 25 '13 at 14:50
vec4 Fr(float u, vec4 specular) {
    return specular + (1.0-specular) * pow(1.0 - u, 5.0);

what's the specular in this function ? I think you specular is wrong,you can change

float Fr(float u) {
    float f = 0.125;  
    float fresnelCoe = f + (1 - f)*pow(1 - u, 5);

f is a constant, different object has difference number


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.