Trying to render a 3d Model... renders 2d

I modified my 2D engine for 3D purpose. I’ve been over my code several times and I can’t detect anything wrong with it. Although, any common thing that could happen isn’t. I have a rare problem, as there are no google results (google is becoming horrible these days).

My model is rendering as a 2D square no matter what I pass. This square can be modified via changing the scale on the ModelView matrix on the stack (I am using my own matrices). The X and the Y scale fine, but the Z is completely ignored for some reason. As for positional stuff, the actual in vec3 position; doesn’t attribute to putting the model verts where it needs to be. I’ve tried many different methods. When I manually try to draw a 3D triangle with Z being at a different coord, I can’t. The model gets compressed to look like a texture drawn on a 2D surface lol.

What is everything that could lead to a Z being ignored?

Here is the things that help the above question:

Creating Transformation Matrix for model:

	public Matrix4f getMatrix() {
		final Matrix4f mat = new Matrix4f();
		mat.setIdentity();
		mat.translate(position, mat);
		mat.rotate(rotation.x, Util.ANGLE_X, mat);
		mat.rotate(rotation.y, Util.ANGLE_Y, mat);
		mat.rotate(rotation.z, Util.ANGLE_Z, mat);
		mat.scale(new Vector3f(scale.x, scale.y, scale.z));
		return mat;
	}

Creating Perspective Matrix for projection

	public static Matrix4f createPerspective(float near, float far, float fov, float aspect) {
		final Matrix4f matrix = new Matrix4f();
		
		float y_scale = (float) ((1f / Math.tan(Math.toRadians(fov / 2f))) * aspect);
		float x_scale = y_scale / aspect;
		float frustum = far - near;
		
		matrix.m00 = x_scale;
		matrix.m11 = y_scale;
		matrix.m22 = -((far + near) / frustum);
		matrix.m23 = -1;
		matrix.m32 = -((2 * near * far) / frustum);
		matrix.m33 = 0;
		
		return matrix;
	}

Creating Camera/View Matrix for camera

	public Matrix4f getMatrix() {
		final Matrix4f mat = new Matrix4f();
		mat.setIdentity();
		mat.translate(position);
		mat.rotate((float) Math.toRadians(rotation.x), Util.ANGLE_X);
		mat.rotate((float) Math.toRadians(rotation.y), Util.ANGLE_Y);
		mat.rotate((float) Math.toRadians(rotation.z), Util.ANGLE_Z);
		return mat;
	}

Rendering an Element

	public static void renderElement(Element element, Matrix4f projection, Matrix4f camera) {
		final ShaderModel shader_model = element.getShaderModel();
		final Model model = element.getModel();
		GL30.glBindVertexArray(model.getVao());
			GL20.glUseProgram(shader_model.getShader().getProgram());
				shader_model.bindTexture(element.getTexture());
				shader_model.updateMatrix(projection, element.getMatrix(), camera);
	//			GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
				GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
			GL20.glUseProgram(0);
		GL30.glBindVertexArray(0);

I bind the attributes as follows. They all match.
The area this code is called from is good. I didn’t modify this part at all because this class just stores uniform locations and has helper functions to upload uniform data. This all works.

		shader.bindAttribute(0, "position");
		shader.bindAttribute(1, "texcoord");
		shader.bindAttribute(2, "normal");

Preparing a VAO

	public static Model loadModel(float[] positions, float[] texture_coords, float[] normals, int[] indicies) {
		final int vao = GL30.glGenVertexArrays();
		GL30.glBindVertexArray(vao);
		final int[] vbos = new int[4];
		vbos[0] = store(0, 3, positions);
		vbos[1] = store(1, 2, texture_coords);
		vbos[2] = store(2, 3, normals);
		vbos[3] = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vbos[3]);
		final IntBuffer ib = BufferUtils.createIntBuffer(indicies.length);
		ib.put(indicies);
		ib.flip();
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, ib, GL15.GL_STATIC_DRAW);
		GL20.glEnableVertexAttribArray(0);
		GL20.glEnableVertexAttribArray(1);
		GL20.glEnableVertexAttribArray(2);
		GL30.glBindVertexArray(0);
		final Model m = new Model(vao, vbos, indicies.length);
		Models.add(m);
		return m;
	}

	public static int store(int id, int len, float[] fltarr) {
		final int vbo = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
		final FloatBuffer fb = BufferUtils.createFloatBuffer(fltarr.length);
		fb.put(fltarr);
		fb.flip();
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, fb, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(id, len, GL11.GL_FLOAT, false, 0, 0);
		return vbo;
	}

default.v

#version 400 core

in vec3 position;
in vec2 texcoord;
in vec3 normal;

out vec2 pass_texcoord;

uniform mat4 matrix_transform;
uniform mat4 matrix_projection;
uniform mat4 matrix_camera;

void main(void) {
	
	pass_texcoord = texcoord;
	gl_Position = matrix_projection * matrix_camera * matrix_transform * vec4(position.xyz, 1.0);
	
}

default.f

#version 400 core

in vec2 pass_texcoord;

out vec4 out_Color;

uniform sampler2D u_texture;

void main(void) {
	
	out_Color = texture(u_texture, pass_texcoord);
	
}

What it turns out

What it should be

Thanks for the help!

Are you rotating the model on each axis every frame? If the shape changes, then your model should be rendering correctly.

Edit: nvm. This was before you posted pictures.

I decided to go copy others code from them asking unrelated mistakes. It now renders -.-

This is what I changed…

layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texcoord;
layout(location = 2) in vec3 normal;

//in vec3 position;
//in vec2 texcoord;
//in vec3 normal;

I’ve always done the latter. Why is it not working now?

Okay so it seems like

layout(location = 0) in vec3 position;

This is the only thing I need to define in this situation. What forces me to have to add layout(location = 0)?

Well it’s here:


store(0, 3, positions);

You are passing the ID (which should be the location) as 0 for positions, where each position is 3 floats in size (vec3, has three components). So in the shader adding the layout will fix your problem.


layout (location = 0) in vec3 pos;

If you do not want to specify the locations in the shader code, you can do so by using glBindAttribLocation method to bind the name to the location like this.


glBindAttribLocation(shaderProgramID, 0, "pos");

If you do not want to bind to your own location, OpenGL gives you the ability to query the location (automatically set when you don’t specify one) and use it to store it using glGetAttribLocation function. Then you have to change your store call to the following.


store(glGetAttribLocation(shaderProgramID, "pos"), 3, positions);

In my opinion I prefer to do the first one, hardcode the locations in the shader code. Hope this helps.

	@Override
	public void init() {
		shader.bindAttribute(0, "position");
		shader.bindAttribute(1, "texcoord");
		shader.bindAttribute(2, "normal");
		
		u_texture = shader.getUniform("u_texture");
		
		matrix_projection = shader.getUniform("matrix_projection");
		matrix_transform = shader.getUniform("matrix_transform");
		matrix_camera = shader.getUniform("matrix_camera");
	}
final int[] vbos = new int[4];
      vbos[0] = store(0, 3, positions);
      vbos[1] = store(1, 2, texture_coords);
      vbos[2] = store(2, 3, normals);
      vbos[3] = GL15.glGenBuffers();

	public void bindAttribute(int location, String name) {
		GL20.glBindAttribLocation(program, location, name);
	}

You explained what I did. However, my question now is why do I have to specify location. This is the first time I’ve ever had to do that. I used to be able to write

in vec3 position;

Well with the given input statement and not specifying the location, from where do you expect OpenGL to read the buffer data into that?


in vec3 position;

You name it as position, but OpenGL does not know what a position is, so you need to specify a location to a buffer so from there the contents of the buffer it can read the data.

Then why are you able to declare a vertex attribute without specifying a location? That is because in old GLSL versions there is no possibility to set a location explicitly, the driver assigns a default location which you had to query with glGetAttribLocation, in the same way you do query the locations of uniforms.

So in your case with no explicit specification of location, the driver allocates a default (but unique) location for the attribute. In case there is nothing bound to that location, OpenGL will read garbage data (clarification needed).

What’s weird about the last statement about garbage data, is my model always comes out constantly.

How I see it…

VAO

VBO position 0
VBO position 1
VBO position 2

Shader

Attribute 0 points to variable position
Attribute 1 points to variable texcoord
Attribute 2 points to variable normal

Bind Vao
Bind shader
Update shader
Unbind shader
Unbind Vao

For you it is working because you are binding the attributes in the init method.


@Override
public void init() {
@@   shader.bindAttribute(0, "position");
@@   shader.bindAttribute(1, "texcoord");
@@   shader.bindAttribute(2, "normal");
      
   u_texture = shader.getUniform("u_texture");
      
   matrix_projection = shader.getUniform("matrix_projection");
   matrix_transform = shader.getUniform("matrix_transform");
   matrix_camera = shader.getUniform("matrix_camera");
}

That is why it is working for you when you are not setting the location in the shader.

And it isn’t working this time which is very odd.