[Solved] Lighting and rotation issues

Basically what’s going on is that when I have objects lit and they are rotated 0 or 180 degrees the lighting is perfect, but when rotated 90 or -90 degrees the lighting is inverted.

Image: models on left are rotated 0 and 180 degrees, models on the right…well you get it.

Code:

		//===================================================
		//===========PROJECTION
		//===================================================
		float[] matrix_array = new float[16];
		gl.glGetFloatv(GL2.GL_PROJECTION_MATRIX, matrix_array, 0);
		Matrix4 m4 = new Matrix4();
		m4.setMatrix(matrix_array);

		FloatBuffer matrix_buffer = Buffers.newDirectFloatBuffer(m4.toArray().length);
		matrix_buffer.put(m4.toArray());
		matrix_buffer.flip();
		shader.setAttributeMatrix4f(gl, false, "projection_matrix", matrix_buffer);
		
		//===================================================
		//===========MODELVIEW
		//===================================================
	    matrix_array = new float[16];
		gl.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, matrix_array, 0);
		m4.setMatrix(matrix_array);

		matrix_buffer = Buffers.newDirectFloatBuffer(m4.toArray().length);
		matrix_buffer.put(m4.toArray());
		matrix_buffer.flip();
		shader.setAttributeMatrix4f(gl, false, "modelview_matrix", matrix_buffer);

		//===================================================
		//===========NORMAL
		//===================================================
		Matrix3 m3 = new Matrix3();
		m4 = m4.invert();
		m4 = m4.transpose();
		m3.copyMatrix(m4.m_mat);

		matrix_buffer = Buffers.newDirectFloatBuffer(m3.toArray().length);
		matrix_buffer.put(m3.toArray());
		matrix_buffer.flip();
		shader.setAttributeMatrix3f(gl, false, "normal_matrix", matrix_buffer);
		
		//===================================================
		//===========MODEL-TO-WORLD
		//===================================================
		Vector3 rotation = m_transform.getRotation();
		Vector3 scale = m_transform.getScale();
		Vector3 translate = m_transform.getTranslate();
		Matrix4 rot_mat = new Matrix4().initRotate(rotation.m_x, rotation.m_y, rotation.m_z);
		Matrix4 scale_mat = new Matrix4().initScale(scale.m_x, scale.m_y, scale.m_z);
		Matrix4 trans_mat = new Matrix4().initTranslate(translate.m_x, translate.m_y, translate.m_z);
		m4 = trans_mat.multiply(rot_mat.multiply(scale_mat));
		m4.transpose();//make column major

		matrix_buffer = Buffers.newDirectFloatBuffer(m4.toArray().length);
		matrix_buffer.put(m4.toArray());
		matrix_buffer.flip();
		shader.setAttributeMatrix4f(gl, false, "model_to_world_matrix", matrix_buffer);

Vert Shader:

in vec2 tex_coord;
in vec3 vert_pos;
in vec3 normal;

uniform vec3 light_pos;
uniform vec3 view_pos;
uniform mat3 normal_matrix;
uniform mat4 modelview_matrix;
uniform mat4 projection_matrix;
uniform mat4 model_to_world_matrix;

out vec2 pass_tex_coord;
out vec3 pass_normal;
out vec3 pass_light_dir;
out vec3 pass_view_dir;

void main(void)
{
   vec4 pos = vec4(vert_pos.xyz, 1.0);
   gl_Position = projection_matrix * modelview_matrix * pos;
   pass_tex_coord = tex_coord;
   
   vec3 vert_pos_world = vec4(model_to_world_matrix * pos).xyz;
   pass_normal = vec4(model_to_world_matrix * vec4(normal, 0)).xyz;
   pass_light_dir = vert_pos_world - light_pos;
}

Frag Shader:

in vec2 pass_tex_coord;
in vec3 pass_normal;
in vec3 pass_light_dir;// L
in vec3 pass_view_dir;//  V

out vec4 out_color;

void main(void)
{
   vec3 n_normal = normalize(pass_normal);
   vec3 n_light_dir = normalize(pass_light_dir);
   float n_dot_l = max(0.0, dot(n_normal, -n_light_dir));
   out_color = vec4(n_dot_l, n_dot_l, n_dot_l, 1.0);
}

Edit: replaced color variable with normal, same values are sent, they are the correct normals. I have verified by outputting them as color

[quote]in vec2 tex_coord;
in vec3 vert_pos;
in vec3 color;
[/quote]
where are your normals?
You need the normal of every face to get the correct
lighting values…

That’s not the issue. Sorry for the confusion the color variable actually contains the normals, I just didn’t refactor. I have since updated my code to reflect this so it won’t be confusing in the future, my bad.

I can assure you that the normals are being sent to the color variable and they are the correct normals.

Old code:


		for(int i = 0, j = 0; i < interleaved_array.length; i += Vertex.SIZE, j++)
		{
			interleaved_array[i+0] = m_vertices[j].m_position.m_x;
			interleaved_array[i+1] = m_vertices[j].m_position.m_y;
			interleaved_array[i+2] = m_vertices[j].m_position.m_z;
			interleaved_array[i+3] = m_vertices[j].m_normal.m_x;
			interleaved_array[i+4] = m_vertices[j].m_normal.m_y;
			interleaved_array[i+5] = m_vertices[j].m_normal.m_z;
			interleaved_array[i+6] = m_vertices[j].m_uv.m_x;
			interleaved_array[i+7] = m_vertices[j].m_uv.m_y;
		}
int vert_pos = gl.glGetAttribLocation(shader.m_program_index, "vert_pos");
		int color = gl.glGetAttribLocation(shader.m_program_index, "color");
		int tex_coord = gl.glGetAttribLocation(shader.m_program_index, "tex_coord");
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, m_vbo_handle[0]);
		gl.glEnableVertexAttribArray(vert_pos);
		gl.glEnableVertexAttribArray(color);
		gl.glEnableVertexAttribArray(tex_coord);
		gl.glVertexAttribPointer(vert_pos, 3, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * (Vertex.SIZE), 0);//start
		gl.glVertexAttribPointer(color, 3, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * (Vertex.SIZE), Buffers.SIZEOF_FLOAT * 3);//12
		gl.glVertexAttribPointer(tex_coord, 2, GL.GL_FLOAT, false, Buffers.SIZEOF_FLOAT * (Vertex.SIZE), Buffers.SIZEOF_FLOAT * 6);//24

After thinking through this I’ve figured out that the reason it’s not working properly is that the rotation around Y is invert -> opposite.

So by changing my model to world matrix as follows:

Vector3 rotation = m_transform.getRotation();
		Vector3 scale = m_transform.getScale();
		Vector3 translate = m_transform.getTranslate();
		//Matrix4 rot_mat = new Matrix4().initRotate(rotation.m_x, rotation.m_y, rotation.m_z); <- This line changes to
		Matrix4 rot_mat = new Matrix4().initRotate(rotation.m_x, -rotation.m_y, rotation.m_z);// <-This
		Matrix4 scale_mat = new Matrix4().initScale(scale.m_x, scale.m_y, scale.m_z);
		Matrix4 trans_mat = new Matrix4().initTranslate(translate.m_x, translate.m_y, translate.m_z);
		m4 = trans_mat.multiply(rot_mat.multiply(scale_mat));
		m4.transpose();//make column major

I have fixed the immediate problem, now I’m curious what the root issue could be. My models show up as expected (translated, rotated, scaled), and neither the X or Z components are broken in the lighting model…