Reputation: 109
I'm currently trying to get a very simple program to work. It just displays a white cross on a black background. The problem is that the rendering of my cross is only working under strange conditions. These are all the conditions i figured out thus far:
glBindVertexArray(0)
is causing the cross not to render even after calling glBindVertexArray(array)
glUseProgram
before every draw callAs you might see i have no idea anymore of what is acutally happening here. How do i fix this bug?
Here is the code:
int axesVBO;
int axesVAO;
int vert, frag;
int program;
@Override
public void display(GLAutoDrawable drawable) {
System.out.println("Render");
GL4 gl = drawable.getGL().getGL4();
gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT);
gl.glBindVertexArray(axesVAO);
gl.glUseProgram(program); //Doesnt work without
gl.glDrawArrays(GL4.GL_LINES, 0, 2);
gl.glDrawArrays(GL4.GL_LINES, 2, 2);
gl.glBindVertexArray(0); //After this line the cross isn't renderd anymore
}
@Override
public void dispose(GLAutoDrawable drawable) {
GL4 gl = drawable.getGL().getGL4();
gl.glDeleteBuffers(1, IntBuffer.wrap(new int[]{axesVBO}));
gl.glDeleteVertexArrays(1, IntBuffer.wrap(new int[]{axesVAO}));
gl.glDeleteProgram(program);
gl.glDeleteShader(vert);
gl.glDeleteShader(frag);
}
@Override
public void init(GLAutoDrawable drawable) {
System.out.println("Init");
GL4 gl = drawable.getGL().getGL4();
IntBuffer buffer = Buffers.newDirectIntBuffer(2);
gl.glGenBuffers(1, buffer);
axesVBO = buffer.get(0);
vert = gl.glCreateShader(GL4.GL_VERTEX_SHADER);
frag = gl.glCreateShader(GL4.GL_FRAGMENT_SHADER);
gl.glShaderSource(vert, 1, new String[]{"#version 410\n in vec2 pos;void main() {gl_Position = vec4(pos, 0, 1);}"}, null);
gl.glShaderSource(frag, 1, new String[]{"#version 410\n out vec4 FragColor;void main() {FragColor = vec4(1, 1, 1, 1);}"}, null);
gl.glCompileShader(vert);
gl.glCompileShader(frag);
if(GLUtils.getShaderiv(gl, vert, GL4.GL_COMPILE_STATUS) == GL.GL_FALSE) {
System.out.println("Vertex shader compilation failed:");
System.out.println(GLUtils.getShaderInfoLog(gl, vert));
} else {
System.out.println("Vertex shader compilation sucessfull");
}
if(GLUtils.getShaderiv(gl, frag, GL4.GL_COMPILE_STATUS) == GL.GL_FALSE) {
System.out.println("Fragment shader compilation failed:");
System.out.println(GLUtils.getShaderInfoLog(gl, frag));
} else {
System.out.println("Fragment shader compilation sucessfull");
}
program = gl.glCreateProgram();
gl.glAttachShader(program, vert);
gl.glAttachShader(program, frag);
gl.glBindAttribLocation(program, 2, "pos"); //Only works when location is > 2
gl.glLinkProgram(program);
if(GLUtils.getProgramiv(gl, program, GL4.GL_LINK_STATUS) == GL.GL_FALSE) {
System.out.println("Program linking failed:");
System.out.println(GLUtils.getProgramInfoLog(gl, program));
} else {
System.out.println("Program linking sucessfull");
}
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, axesVBO);
gl.glBufferData(GL4.GL_ARRAY_BUFFER, Float.BYTES * 8, FloatBuffer.wrap(new float[]{-1f, 0, 1f, 0, 0, 1f, 0, -1f}), GL4.GL_STATIC_DRAW);
gl.glUseProgram(program);
buffer.clear();
gl.glGenVertexArrays(1, buffer);
axesVAO = buffer.get();
gl.glBindVertexArray(axesVAO);
int pos = gl.glGetAttribLocation(program, "pos");
gl.glEnableVertexAttribArray(pos);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, axesVBO);
gl.glVertexAttribPointer(pos, 2, GL4.GL_FLOAT, false, 0, 0);
//Commented out for testing reasons (doesnt work when active)
//gl.glBindVertexArray(0);
gl.glClearColor(0f, 0f, 0f, 1f);
}
Upvotes: 2
Views: 180
Reputation: 7180
The conditions you figured out look strange. Anyway in general, having a clean and simple code helps a lot to avoid nasty bugs. Start clean and simple and then built it up :)
Few considerations:
int
for vbo and vao, use directly direct buffersvert
and frag
if they are gonna be used only in the init
, declare them locally in the method insteadGLBuffers.newDirect*Buffer(...)
ShaderCode.create
and ShaderProgram
) to compile your shaders, it offloads you from work and potential bugs and includes a deeper check on any step during the whole shader creation (sometimes even too much, but nowadays shaders are so fast to compile it doesn't matter)ARB_explicit_attrib_location
, you can check with gl4.isExtensionAvailable("GL_ARB_explicit_attrib_location");
, use it everywhere you can, it will avoid a lot of potential bugs and overhead with any kind of location (such as glBindAttribLocation
and glGetAttribLocation
)glBufferData
so that jogl doesn't have to create it by itself underneath and you can keep trace of it to deallocate itinit
clean and readable. You are mixing a lot of stuff together. For example you generate the vbo at the begin, then you create the program, then you upload data to the vbo.gl.glUseProgram(program);
in the init
, unless your idea is to bind it and leave it bound. Anyway, normally, program is part of the initialization phase before a rendering call, so better to move it in the display()
.glClearBuffer
to glClear
gl.glDrawArrays(GL4.GL_LINES, 0, 2);
has no utility because you are passing zero as the number of verticesUpvotes: 1