# Specular/Diffuse light on an icosahedron opengl

I'm having a problem with my model here. I draw an icosahedron using GLUT, and the radius is set to 0.8. The info of the coordinates are listed below: (X and Z are calculated since our radius is 0.8)

 private static final float X = .4205912828f;
private static final float Z = .6805166955f;
private static final float[][] idata =
{
{-X, 0, Z},
{X, 0, Z},
{-X, 0, -Z},
{X, 0, -Z},
{0, Z, X},
{0, Z, -X},
{0, -Z, X},
{0, -Z, -X},
{Z, X, 0},
{-Z, X, 0},
{Z, -X, 0},
{-Z, -X, 0}
};

private static final int[][] index =
{
{0, 4, 1},
{0, 9, 4},
{9, 5, 4},
{4, 5, 8},
{4, 8, 1},
{8, 10, 1},
{8, 3, 10},
{5, 3, 8},
{5, 2, 3},
{2, 7, 3},
{7, 10, 3},
{7, 6, 10},
{7, 11, 6},
{11, 0, 6},
{0, 1, 6},
{6, 1, 10},
{9, 0, 11},
{9, 11, 2},
{9, 2, 5},
{7, 2, 11},
};


I calculate the vertex normal using the glut method as well:

private static void icosahedron(final GL2 gl) {
int i;
for (i = 0; i <= 19; i++) {
drawtriangle(gl, i, idata, index);
}
}
private static void diff3(final float[] a, final float[] b, final float[] c) {
c[0] = a[0] - b[0];
c[1] = a[1] - b[1];
c[2] = a[2] - b[2];
}

private static void crossprod(final float[] v1, final float[] v2, final float[] prod) {
final float[] p = new float[3];         /* in case prod == v1 or v2 */

p[0] = v1[1] * v2[2] - v2[1] * v1[2];
p[1] = v1[2] * v2[0] - v2[2] * v1[0];
p[2] = v1[0] * v2[1] - v2[0] * v1[1];
prod[0] = p[0];
prod[1] = p[1];
prod[2] = p[2];
}

private static void normalize(final float[] v) {
float d;

d = (float) Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if (d == 0.0) {
v[0] = d = 1.0f;
}
d = 1 / d;
v[0] *= d;
v[1] *= d;
v[2] *= d;
}

private static void recorditem(final GL2 gl, final float[] n1, final float[] n2, final float[] n3) {
final float[] q0 = new float[3];
final float[] q1 = new float[3];
final float[] q2 = new float[3];
diff3(n1, n2, q0);
diff3(n2, n3, q1);
crossprod(q0, q1, q2);
normalize(q2);
System.out.format("%.5f, %.5f, %.5f",q2[0],q2[1],q2[2]);
gl.glBegin(GL.GL_TRIANGLES);
gl.glNormal3fv(q2,0);
gl.glVertex3fv(n1, 0);
gl.glVertex3fv(n2, 0);
gl.glVertex3fv(n3, 0);
gl.glEnd();
}

private static void subdivide(final GL2 gl, final float[] v0, final float[] v1, final float[] v2) {
int depth;
final float[] w0 = new float[3];
final float[] w1 = new float[3];
final float[] w2 = new float[3];
float l;
int i, j, k, n;

depth = 1;
for (i = 0; i < depth; i++) {
for (j = 0; i + j < depth; j++) {
k = depth - i - j;
for (n = 0; n < 3; n++) {
w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
/ depth;
w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
/ depth;
}
l = (float) Math.sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
w0[0] /= l;
w0[1] /= l;
w0[2] /= l;
l = (float) Math.sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
w1[0] /= l;
w1[1] /= l;
w1[2] /= l;
l = (float) Math.sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
w2[0] /= l;
w2[1] /= l;
w2[2] /= l;
recorditem(gl, w0, w1, w2);
}
}
}

private static void drawtriangle(final GL2 gl, final int i, final float[][] data, final int[][] ndx) {
final float[] x0 = data[ndx[i][0]];
final float[] x1 = data[ndx[i][1]];
final float[] x2 = data[ndx[i][2]];
subdivide(gl, x0, x1, x2);
}


However, the reflection of the light does not look right on the icosahedron.

attribute vec3 inposition;//in vec3 position;          //for #version 130
attribute vec4 incolor;
attribute vec3 innormal;
attribute vec2 intexcoord0;
varying vec3 normal;
varying vec4 color;
varying vec2 texcoord;
varying vec3 pos;
uniform mat4 mat[4];

void main(void)
{
normal = normalize((mat[3]*vec4(innormal,0.0)).xyz);
color = incolor;
texcoord = intexcoord0;
gl_Position = mat[0]*mat[1]*vec4(inposition, 1.0);
//  gl_Position = vec4(inposition, 1.0);
pos = gl_Position.xyz;
}


Here innormal is the vertex normal, and inposition are the coordinates of the vertices.

And my frag shader is :

uniform sampler2D texture0;
uniform vec3 lightpos;
uniform vec3 lightColor;
uniform vec3 objectColor;
varying vec3 normal;
varying vec4 color;
varying vec2 texcoord;
varying vec3 pos;

void main (void){
//  gl_FragColor = max(texture2D(texture0, texcoord),color.xyzw);
//  gl_FragColor = texture2D(texture0, texcoord);
//  gl_FragColor = vec4(0.3, 0.8, 0.2, 1.0);
//  vec2 dfdx = abs(dFdx(texcoord));
//  vec2 dfdy = abs(dFdy(texcoord));
//  float d = max(max(dfdx.x,dfdx.y),max(dfdy.x,dfdy.y));
//  gl_FragColor = vec4(d*20,0,0,1);

vec3 light = lightpos- pos;
//light = lightpos;

vec3 norm = normalize(normal);
vec3 eye_vector = vec3(0.0);
vec3 viewDir = normalize(eye_vector - pos);
vec3 lightDir = normalize(light);
vec3 reflectDir = reflect(lightDir,norm);
float spec = pow(dot(viewDir,reflectDir), 100.0);
float specularStrength = 0.5;
vec3 lightColor = vec3(1.0);
vec3 spect = spec*specularStrength*lightColor;

gl_FragColor = vec4((0.9*max(dot(normal, normalize(light)),0.0)+0.1)*color.xyz,1.0) + vec4(vec3(spect),1.0);


The lightpos is the position of the light which is (0,0,10);

Somehow the result looks like this:

which doesn't look right. Could anyone give me some hints please?

This is the vertex data and

This is how mat4 produced. And the following is the normal output by @PaulHK 's idea, and it is broken.

• How is mat[3] calculated ? I notice your diffuse shading is also broken so I would start by looking at your normals. Maybe outputting the 'norm' variable as your fragment shader output so you can visualise if they are correct. – PaulHK Feb 1 at 8:16
• Please copy and paste the text into the question instead of adding screenshots of text. Screenshots aren't searchable so it's harder for people to find and answer your question. They're also not useful to blind people who use a screen-reader to use the site. – Dan Hulme Feb 4 at 13:10