Hi There
I'm trying to get VBOs working with shader vertex attribute arrays. I keep getting this exception:
Exception in thread "main" org.lwjgl.opengl.OpenGLException: Cannot use Buffers when Array Buffer Object is enabled
at org.lwjgl.opengl.GLChecks.ensureArrayVBOdisabled(GLChecks.java:87)
at org.lwjgl.opengl.GL20.glVertexAttribPointer(GL20.java:890)
at jthrust_phys2d.test.TestVBO_Shader.<init>(TestVBO_Shader.java:118)
at jthrust_phys2d.test.TestVBO_Shader.main(TestVBO_Shader.java:39)
When I try to do a simple VBO by itself, it works fine but trying to introduce the shader vertex attribute arrays is proving to be a problem. I've attached the full code of a test case below. If someone could let me know what I'm doing wrong, I'd like to know :o)
Cheers!
package jthrust_phys2d.test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import static org.lwjgl.opengl.GL31.*;
import static org.lwjgl.util.glu.GLU.*;
/**
*
* @author peter
*/
public class TestVBO_Shader {
private final int screenWidth;
private final int screenHeight;
private final float FOV = 60f;
private final int vertexBufferID;
private final int colourBufferID;
private final int indexBufferID;
private final int basicShader;
/**
*
* @param args
*/
public static void main(String[] args){
try {
new TestVBO_Shader().start();
} catch (LWJGLException ex) {
ex.printStackTrace();
}
}
/**
*
* @throws LWJGLException
*/
public TestVBO_Shader() throws LWJGLException{
final float sScale = 0.5f;
screenWidth = (int)(sScale * 1000);
screenHeight = (int)(sScale * 800);
Display.setDisplayMode(new DisplayMode(screenWidth,screenHeight));
Display.create();
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
//--- shader ---
basicShader = ARBShaderObjects.glCreateProgramObjectARB();
int basicVert = createVertShader("shaders/basic.vert");
int basicFrag = createFragShader("shaders/basic.frag");
ARBShaderObjects.glAttachObjectARB(basicShader, basicVert);
ARBShaderObjects.glAttachObjectARB(basicShader, basicFrag);
glBindAttribLocation(basicShader, 0, "VertexPosition");
glBindAttribLocation(basicShader, 1, "VertexColor");
ARBShaderObjects.glLinkProgramARB(basicShader);
ARBShaderObjects.glValidateProgramARB(basicShader);
printLogInfo(basicShader);
//--- vbo ---
vertexBufferID = createVBOID();
colourBufferID = createVBOID();
indexBufferID = createVBOID();
FloatBuffer vertBuf = BufferUtils.createFloatBuffer(10);
vertBuf.put(new float[]{
-5f, -5f, 0f,
5f, -5f, 0f,
0f, 5f, 0f });
FloatBuffer colBuf = BufferUtils.createFloatBuffer(12);
colBuf.put(new float[]{
1f, 0f, 0f, 1f,
0f, 1f, 0f, 1f,
0f, 0f, 1f, 1f});
IntBuffer intBuf = BufferUtils.createIntBuffer(3);
intBuf.put(new int[]{0,1,2});
vertBuf.rewind();
colBuf.rewind();
intBuf.rewind();
bufferData(vertexBufferID, vertBuf);
bufferData(colourBufferID, colBuf);
bufferElementData(indexBufferID, intBuf);
vertBuf.rewind();
colBuf.rewind();
intBuf.rewind();
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glVertexAttribPointer(0, 3, false, 0, vertBuf); //<<< this line is where the exception is raised
glBindBuffer(GL_ARRAY_BUFFER, colourBufferID);
glVertexAttribPointer(1, 3, false, 0, colBuf);
}
public static int createVBOID() {
IntBuffer buffer = BufferUtils.createIntBuffer(1);
ARBVertexBufferObject.glGenBuffersARB(buffer);
return buffer.get(0);
}
public static void bufferData(int id, FloatBuffer buffer) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer,
ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}
public static void bufferElementData(int id, IntBuffer buffer) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, id);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, buffer,
ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}
/**
*
*/
public void start(){
while(true){
render();
Display.update();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
//ignore
}
if(Display.isCloseRequested()){
break;
}
}
}
/*
* With the exception of syntax, setting up vertex and fragment shaders is the same. @param the name and
* path to the vertex shader
*/
private int createVertShader(String filename) {
//vertShader will be non zero if succefully created
int vShdr = ARBShaderObjects.glCreateShaderObjectARB(ARBVertexShader.GL_VERTEX_SHADER_ARB);
//if created, convert the vertex shader code to a String
if (vShdr == 0) {
return 0;
}
String vertexCode = "";
String line;
try {
BufferedReader reader = new BufferedReader(new FileReader(filename));
while ((line = reader.readLine()) != null) {
vertexCode += line + "\n";
}
} catch (Exception e) {
System.out.println("Fail reading vertex shading code");
return 0;
}
/*
* associate the vertex code String with the created vertex shader and compile
*/
ARBShaderObjects.glShaderSourceARB(vShdr, vertexCode);
ARBShaderObjects.glCompileShaderARB(vShdr);
//if there was a problem compiling, reset vertShader to zero
if (!printLogInfo(vShdr)) {
vShdr = 0;
}
//if zero we won't be using the shader
return vShdr;
}
/**
* same as per the vertex shader except for method syntax
*/
private int createFragShader(String filename) {
int fShdr = ARBShaderObjects.glCreateShaderObjectARB(ARBFragmentShader.GL_FRAGMENT_SHADER_ARB);
if (fShdr == 0) {
return 0;
}
String fragCode = "";
String line;
try {
BufferedReader reader = new BufferedReader(new FileReader(filename));
while ((line = reader.readLine()) != null) {
fragCode += line + "\n";
}
} catch (Exception e) {
System.out.println("Fail reading fragment shading code");
return 0;
}
ARBShaderObjects.glShaderSourceARB(fShdr, fragCode);
ARBShaderObjects.glCompileShaderARB(fShdr);
if (!printLogInfo(fShdr)) {
fShdr = 0;
}
return fShdr;
}
/**
*
* @param obj
* @return
*/
private static boolean printLogInfo(int obj) {
IntBuffer iVal = BufferUtils.createIntBuffer(1);
ARBShaderObjects.glGetObjectParameterARB(obj,
ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, iVal);
int length = iVal.get();
if (length > 1) {
// We have some info we need to output.
ByteBuffer infoLog = BufferUtils.createByteBuffer(length);
iVal.flip();
ARBShaderObjects.glGetInfoLogARB(obj, iVal, infoLog);
byte[] infoBytes = new byte[length];
infoLog.get(infoBytes);
String out = new String(infoBytes);
System.out.println("Info log:\n" + out);
} else {
return true;
}
return false;
}
/**
*
*/
void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// --- set lighting and projection matrix -----------
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//camera.applyPerspective(gl, glu);
float aspect = (float) screenWidth / (float) screenHeight;
gluPerspective(FOV, aspect, 1, 1000);
// --- set model view matrix ----------------
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
final float scale = 1f;
gluLookAt(0, 0, 10f,
0, 0, 0,
0, 1, 0);
// store the view transform
glPushMatrix();
glEnableClientState(GL_VERTEX_ARRAY);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vertexBufferID);
glVertexPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_COLOR_ARRAY);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, colourBufferID);
glColorPointer(4, GL_FLOAT, 0, 0);
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
glDrawRangeElements(GL_TRIANGLES, 0, 3, 3, GL_UNSIGNED_INT, 0);
// --- debug axis at world origin ---
final float axis = 500.0f;
glBegin(GL_LINES);
glColor3f(1,0,0);
glVertex3f(0,0,0); glVertex3f(axis,0,0);
glColor3f(0,1,0);
glVertex3f(0,0,0); glVertex3f(0,axis,0);
glColor3f(0,0,1);
glVertex3f(0,0,0); glVertex3f(0,0,axis);
glEnd();
glPopMatrix();
}
}