I'm trying to render something with LWJGL and I was following a tutorial (this one) and I had finished what has been written, however I wanted lighting so I followed a tutorial I had found (this one). Now my application, upon starting up just crashes, with a very useless crash log.
Render Function:
public void renderMesh(GameObject object, Camera camera) {
GL30.glBindVertexArray(object.getMesh().getVAO());
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
GL30.glEnableVertexAttribArray(2);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, object.getMesh().getIBO());
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMesh().getMaterial().getTextureID());
shader.bind();
shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale()));
shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation()));
shader.setUniform("projection", window.getProjectionMatrix());
shader.setUniform("lightPos", new Vector3f(0, 10, 0));
GL11.glDrawElements(GL11.GL_TRIANGLES, object.getMesh().getIndices().length, GL11.GL_UNSIGNED_INT, 0);
shader.unbind();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL30.glDisableVertexAttribArray(0);
GL30.glDisableVertexAttribArray(1);
GL30.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
Vertex Shader:
#version 460
in vec3 position;
in vec3 normal;
in vec3 color;
in vec2 textureCoord;
out vec2 passTextureCoord;
out vec3 passNormal;
out vec3 passPosition;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
gl_Position = projection * view * model * vec4(position, 1.0);
passNormal = normal;
passTextureCoord = textureCoord;
passPosition = vec3(model * vec4(position, 1.0));
}
Fragment Shader:
#version 460
in vec2 passTextureCoord;
in vec3 passNormal;
in vec3 passPosition;
out vec4 color;
uniform sampler2D tex;
uniform vec3 lightPos;
void main() {
vec3 lightColor = vec3(1.0);
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
vec3 norm = normalize(passNormal);
vec3 lightDir = normalize(lightPos - passPosition);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
vec3 result = (ambient + diffuse) * 0.85;
color = vec4(result, 1.0) * texture(tex, passTextureCoord);
}
Stacktrace:
j org.lwjgl.opengl.GL11C.nglDrawElements(IIIJ)V+0
j org.lwjgl.opengl.GL11C.glDrawElements(IIIJ)V+4
j org.lwjgl.opengl.GL11.glDrawElements(IIIJ)V+4
j rendering.Renderer.renderMesh(Lobject/GameObject;Lobject/Camera;)V+155
...
Can anyone see a problem?
Edit: Mesh.java
public class Mesh {
private Vertex[] vertices;
private int[] indices;
private Material material;
private int vao, pbo, ibo, cbo, tbo;
public Mesh(Vertex[] vertices, int[] indices, Material material) {
this.vertices = vertices;
this.indices = indices;
this.material = material;
}
public void create() {
material.create();
vao = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vao);
FloatBuffer positionBuffer = BufferUtils.createFloatBuffer(vertices.length * 3);
float[] positionData = new float[vertices.length * 3];
for (int i = 0; i < vertices.length; i++) {
positionData[i * 3] = vertices[i].getPosition().getX();
positionData[i * 3 + 1] = vertices[i].getPosition().getY();
positionData[i * 3 + 2] = vertices[i].getPosition().getZ();
}
positionBuffer.put(positionData).flip();
pbo = storeData(positionBuffer, 0, 3);
FloatBuffer textureBuffer = BufferUtils.createFloatBuffer(vertices.length * 2);
float[] textureData = new float[vertices.length * 2];
for (int i = 0; i < vertices.length; i++) {
textureData[i * 2] = vertices[i].getTextureCoord().getX();
textureData[i * 2 + 1] = vertices[i].getTextureCoord().getY();
}
textureBuffer.put(textureData).flip();
tbo = storeData(textureBuffer, 2, 2);
IntBuffer indicesBuffer = BufferUtils.createIntBuffer(indices.length);
indicesBuffer.put(indices).flip();
ibo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ibo);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
}
private int storeData(FloatBuffer buffer, int index, int size) {
int bufferID = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, bufferID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(index, size, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
return bufferID;
}
public void destroy() {
GL15.glDeleteBuffers(pbo);
GL15.glDeleteBuffers(cbo);
GL15.glDeleteBuffers(ibo);
GL15.glDeleteBuffers(tbo);
GL30.glDeleteVertexArrays(vao);
material.destroy();
}
public Vertex[] getVertices() {
return vertices;
}
public int[] getIndices() {
return indices;
}
public int getVAO() {
return vao;
}
public int getPBO() {
return pbo;
}
public int getCBO() {
return cbo;
}
public int getTBO() {
return tbo;
}
public int getIBO() {
return ibo;
}
public Material getMaterial() {
return material;
}
}
Shader.java
public class Shader {
private String vertexFile, fragmentFile;
private int vertexID, fragmentID, programID;
public Shader(String vertexPath, String fragmentPath) {
vertexFile = FileUtil.loadAsString(vertexPath);
fragmentFile = FileUtil.loadAsString(fragmentPath);
}
public void create() {
programID = GL20.glCreateProgram();
vertexID = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexID, vertexFile);
GL20.glCompileShader(vertexID);
if (GL20.glGetShaderi(vertexID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
System.err.println("Vertex Shader: " + GL20.glGetShaderInfoLog(vertexID));
return;
}
fragmentID = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentID, fragmentFile);
GL20.glCompileShader(fragmentID);
if (GL20.glGetShaderi(fragmentID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
System.err.println("Fragment Shader: " + GL20.glGetShaderInfoLog(fragmentID));
return;
}
GL20.glAttachShader(programID, vertexID);
GL20.glAttachShader(programID, fragmentID);
GL20.glLinkProgram(programID);
if (GL20.glGetProgrami(programID, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
System.err.println("Program Linking: " + GL20.glGetProgramInfoLog(programID));
return;
}
GL20.glValidateProgram(programID);
if (GL20.glGetProgrami(programID, GL20.GL_VALIDATE_STATUS) == GL11.GL_FALSE) {
System.err.println("Program Validation: " + GL20.glGetProgramInfoLog(programID));
return;
}
}
public int getUniformLocation(String name) {
return GL20.glGetUniformLocation(programID, name);
}
public void setUniform(String name, float value) {
GL20.glUniform1f(getUniformLocation(name), value);
}
public void setUniform(String name, int value) {
GL20.glUniform1i(getUniformLocation(name), value);
}
public void setUniform(String name, boolean value) {
GL20.glUniform1i(getUniformLocation(name), value ? 1 : 0);
}
public void setUniform(String name, Vector2f value) {
GL20.glUniform2f(getUniformLocation(name), value.getX(), value.getY());
}
public void setUniform(String name, Vector3f value) {
GL20.glUniform3f(getUniformLocation(name), value.getX(), value.getY(), value.getZ());
}
public void setUniform(String name, Matrix4f value) {
FloatBuffer matrix = MemoryUtil.memAllocFloat(Matrix4f.SIZE * Matrix4f.SIZE);
matrix.put(value.getAll()).flip();
GL20.glUniformMatrix4fv(getUniformLocation(name), true, matrix);
}
public void bind() {
GL20.glUseProgram(programID);
}
public void unbind() {
GL20.glUseProgram(0);
}
public void destroy() {
GL20.glDetachShader(programID, vertexID);
GL20.glDetachShader(programID, fragmentID);
GL20.glDeleteShader(vertexID);
GL20.glDeleteShader(fragmentID);
GL20.glDeleteProgram(programID);
}
}
Window Setup:
GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
windowPosX[0] = (videoMode.width());
windowPosY[0] = (videoMode.height() - height) / 2;
GLFW.glfwSetWindowPos(window, windowPosX[0], windowPosY[0]);
GLFW.glfwMakeContextCurrent(window);
GL.createCapabilities();
GL11.glShadeModel(GL_SMOOTH);
GL11.glEnable(GL_DEPTH_TEST);
GL11.glEnable(GL_LIGHTING);
GL11.glEnable(GL_LIGHT0);
GL11.glLightModelfv(GL_LIGHT_MODEL_AMBIENT, new float[]{0.1f, 0.05f, 0.05f, 1f});
GL11.glLightfv(GL_LIGHT0, GL_POSITION, new float[]{0, 0, 0, 1});
GL11.glEnable(GL_CULL_FACE);
GL11.glCullFace(GL_BACK);
GL11.glEnable(GL_COLOR_MATERIAL);
GL11.glColorMaterial(GL_FRONT, GL_DIFFUSE);
Another note: I'm the add render function from another .jar file that is loaded by the program. Its unlikely it's the issue, as without lighting the program worked.
The issue is that you never setup the vertex source (VBO - via glVertexAttribPointer
) for the generic vertex attribute with index 1
, but you enable that attribute via glEnableVertexAttribArray(1)
. You cannot have an enabled generic vertex attribute that is uninitialized.
You only call storeData(positionBuffer, 0, 3)
and storeData(positionBuffer, 2, 3)
but never for generic vertex attribute index 1
.
This causes the crash.