I'm working on what will eventually be a terrain drawer, however at the moment I am just trying to get a basic pair of triangles to draw with glDrawElements. The code looks as such:
public class TerrainFlat extends AbstractTerrain {
IntBuffer ib = BufferUtils.createIntBuffer(3);
int vHandle = ib.get(0);
int cHandle = ib.get(1);
int iHandle = ib.get(2);
FloatBuffer vBuffer = BufferUtils.createFloatBuffer(19);
FloatBuffer cBuffer = BufferUtils.createFloatBuffer(18);
ShortBuffer iBuffer = BufferUtils.createShortBuffer(6);
#Override
public void initilize(){
float[] vertexData = {50, 20, 100, 50, -20, 100, 10, -20, 100, -10, -20, 100, -50, -20, 100, -50, 20, 100};
float[] colorData = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0 , 0 , 1 , 0 , 1 , 0 , 1 , 0 , 0 };
short[] indexData = {0,1,2,3,4,5};
vBuffer.put(vertexData);
vBuffer.flip();
cBuffer.put(colorData);
cBuffer.flip();
iBuffer.put(indexData);
iBuffer.flip();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iHandle);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vHandle);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cHandle);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, cBuffer, GL_STATIC_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
#Override
public void setUp(float posX, float posY, float posZ){
}
#Override
public void draw(){
glClear(GL_COLOR_BUFFER_BIT);
glGenBuffersARB(ib);
vHandle = ib.get(0);
cHandle = ib.get(1);
iHandle = ib.get(2);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vHandle);
glVertexPointer(3, GL_FLOAT, 3 << 2 , 0L);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cHandle);
glColorPointer(3, GL_FLOAT, 3 << 2 , 0L);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, iHandle);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0L);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
#Override
public void destroy(){
ib.put(0, vHandle);
ib.put(1, cHandle);
ib.put(2, iHandle);
glDeleteBuffersARB(ib);
}
}
This does not draw anything, the screen is entirely black. GL_CULL_FACE is not enabled, and there is no lighting (or lack thereof) to cause this error. Moving the data binding into the Draw() function lets it work (if you want I can add that code to this). This however means I create my buffer's every draw function (ie: bad). I'm wondering outright what I'm doing wrong here, because I've moved it around and slapped it silly for 4 days now.
You're setting vHandle, cHandle and iHandle to 0.
You never need to create the IntBuffer in line 1 anyway. Replace
int vHandle = ib.get(0);
int cHandle = ib.get(1);
int iHandle = ib.get(2);
with
int vHandle = glGenBuffers();
int cHandle = glGenBuffers();
int iHandle = glGenBuffers();
Related
Do you have any idea why this isn't working?
The old immediate mode works but I want to use VAO and VBOs.
(PS: I know the VOA creation should only be created once, but I build it all in this method for the test. I will move thoses lines after testing)
private void allocateIndexBuffer(GL2 graphics, int[] indices) {
int[] id = new int[1];
graphics.glGenBuffers(1, id, 0);
int vboId = id[0];
graphics.glBindBuffer(GL2.GL_ELEMENT_ARRAY_BUFFER, vboId);
IntBuffer buffer = IntBuffer.allocate(indices.length);
buffer.put(0, indices);
buffer.flip();
graphics.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indices.length, buffer, GL2.GL_DYNAMIC_DRAW);
//graphics.glDeleteBuffers(vboId, buffer); TODO: clean up when on closing
}
private void allocateAttributeBuffer(GL2 graphics, int attribute, float[] data) {
int[] id = new int[1];
graphics.glGenBuffers(1, id, 0);
int vboId = id[0];
graphics.glBindBuffer(GL2.GL_ARRAY_BUFFER, vboId); //juste remplir vboId ou le remplacer à chaque fois ?
FloatBuffer buffer = FloatBuffer.allocate(data.length);
buffer.put(0, data);
buffer.flip();
graphics.glBufferData(GL2.GL_ARRAY_BUFFER, data.length, buffer, GL2.GL_DYNAMIC_DRAW);
graphics.glVertexAttribPointer(0, 2, GL2.GL_FLOAT, false, 0, 0); //once the buffer is bound
graphics.glEnableVertexAttribArray(0);
graphics.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0);
//graphics.glDeleteBuffers(vboId, buffer); TODO: clean up when on closing
//graphics.glDeleteVertexArrays(vboId, null); TODO: clean up vaos
}
#Override
protected void draw(GL2 graphics) {
String mode = "new";
if (mode.equals("new")) {
float[] vertices = {
bounds.getX(), bounds.getY(),
bounds.getX(), bounds.getY() + bounds.getHeight(),
bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight(),
bounds.getX() + bounds.getWidth(), bounds.getY(),
};
int[] indices = { 0, 1, 2, 2, 1, 3 };
//creation vao
int[] id = new int[1];
graphics.glGenVertexArrays(1, id, 0);
int vaoId = id[0];
graphics.glBindVertexArray(vaoId);
allocateIndexBuffer(graphics, indices);
allocateAttributeBuffer(graphics, 0, vertices);
graphics.glBindVertexArray(0);
//render
graphics.glBindVertexArray(vaoId);
graphics.glEnableVertexAttribArray(0);
graphics.glDrawElements(GL2.GL_TRIANGLES, indices.length, GL2.GL_UNSIGNED_INT, 0);
graphics.glDisableVertexAttribArray(0);
graphics.glBindVertexArray(0);
graphics.glFlush();
} else if (mode.equals("old")) {
graphics.glColor3f(255, 0, 0);
graphics.glBegin(GL2.GL_QUADS);
graphics.glVertex2f(bounds.getX(), bounds.getY());
graphics.glVertex2f(bounds.getX() + bounds.getWidth(), bounds.getY());
graphics.glVertex2f(bounds.getX() + bounds.getWidth(), bounds.getY() + bounds.getHeight());
graphics.glVertex2f(bounds.getX(), bounds.getY() + bounds.getHeight());
graphics.glEnd();
}
}
The size of the buffer has to be specified in bytes (see glBufferData);
graphics.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indices.length, buffer, GL2.GL_DYNAMIC_DRAW);
graphics.glBufferData(GL2.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * 4,
buffer, GL2.GL_DYNAMIC_DRAW);
graphics.glBufferData(GL2.GL_ARRAY_BUFFER, data.length, buffer, GL2.GL_DYNAMIC_DRAW);
graphics.glBufferData(GL2.GL_ARRAY_BUFFER, data.capacity() * 4,
buffer, GL2.GL_DYNAMIC_DRAW);
I try to use transform features to create a particle system, so there are 2 tranform buffer and 2 array buffer, use ping-pong to switch.
And my shader is simple, just keep add source position.
gs_Position = vs_Position[0] + vec3(1, 0, 1);
If use glDrawTransformFeedback(), 2 buffer will keep original data, not change.But if I switch to glDrawArrays(), then ping-pong works, position value keep increase.
Initial code
shader.setupShaderFromFile(GL_VERTEX_SHADER, "feedback.vert");
shader.setupShaderFromFile(GL_GEOMETRY_SHADER, "feedback.geom");
const GLchar* feedbackVaryings[] = { "gs_Position", "gs_Velocity" };
glTransformFeedbackVaryings(shader.getProgram(), 2, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
shader.linkProgram();
glGenTransformFeedbacks(2, tfo);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Particle* p = new Particle[2];
p[0].position = glm::vec3(1, 2, 3);
p[1].position = glm::vec3(2, 3, 4);
glGenBuffers(2, bfo);
glBindBuffer(GL_ARRAY_BUFFER, bfo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle)*2, p, GL_STATIC_DRAW);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo[0]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bfo[0]);
glBindBuffer(GL_ARRAY_BUFFER, bfo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Particle)*2, nullptr, GL_STATIC_READ);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo[1]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bfo[1]);
perform transform
int from = pid;
int to = (pid + 1) % 2;
glEnable(GL_RASTERIZER_DISCARD);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo[to]);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bfo[to]);
shader.begin();
glBindBuffer(GL_ARRAY_BUFFER, bfo[from]);
{
GLint inputAttrib = shader.getAttributeLocation("a_Position");
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(inputAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)offsetof(Particle, position));
}
{
GLint inputAttrib = shader.getAttributeLocation("a_Velocity");
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(inputAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)offsetof(Particle, velocity));
}
glBeginTransformFeedback(GL_POINTS);
//glDrawArrays(GL_POINTS, 0, 2);
glDrawTransformFeedback(GL_POINTS, tfo[from]);
glEndTransformFeedback();
shader.end();
glDisable(GL_RASTERIZER_DISCARD);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);
I've been having problems storing texture coordinate points in a VBO, and then telling OpenGL to use it when it's time to render. In the code below, what I should be getting is a nice 16x16 texture on a square I am making using quads. However what I do get is the first top left pixel of the image instead which is red, so I get a big red square. Please tell me what I am doing wrong in great detail.
public void start() {
try {
Display.setDisplayMode(new DisplayMode(800,600));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
// init OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
//loadTextures();
TextureManager.init();
makeCube();
// init OpenGL here
while (!Display.isCloseRequested()) {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
// render OpenGL here
renderCube();
Display.update();
}
Display.destroy();
}
public static void main(String[] argv) {
Screen screen = new Screen();
screen.start();
}
int cube;
int texture;
private void makeCube() {
FloatBuffer cubeBuffer;
FloatBuffer textureBuffer;
//Tried using 0,0,16,0,16,16,0,16 for textureData did not work.
float[] textureData = new float[]{
0,0,
1,0,
1,1,
0,1};
textureBuffer = BufferUtils.createFloatBuffer(textureData.length);
textureBuffer.put(texture);
textureBuffer.flip();
texture = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, texture);
glBufferData(GL_ARRAY_BUFFER, textureBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
float[] cubeData = new float[]{
/*Front Face*/
100, 100,
100 + 200, 100,
100 + 200, 100 + 200,
100, 100 + 200};
cubeBuffer = BufferUtils.createFloatBuffer(cubeData.length);
cubeBuffer.put(cubeData);
cubeBuffer.flip();
cube = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, cube);
glBufferData(GL_ARRAY_BUFFER, cubeBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
private void renderCube(){
TextureManager.texture.bind();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, texture);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, cube);
glVertexPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
I believe your problem is in the argument to textureBuffer.put() in this code fragment:
textureBuffer = BufferUtils.createFloatBuffer(textureData.length);
textureBuffer.put(texture);
textureBuffer.flip();
texture is a variable of type int, which has not even been initialized yet. You later use it as a buffer name. The argument should be textureData instead:
textureBuffer.put(textureData);
I normally try to focus on functionality over style when answering questions here, but I can't help it this time: IMHO, texture is a very unfortunate name for a buffer name. It's not only a style and readability question. If you used descriptive names for the variables, you most likely would have spotted this problem immediately.
Say you named the variable for the buffer name bufferId (I call object identifiers "id", even though the official OpenGL terminology is "name"), and the buffer holding the texture coordinates textureCoordBuf. The statement in question would then become:
textureCoordBuf.put(bufferId);
which would jump out as highly suspicious from even a very superficial look at the code.
I was drawing a square with coordinates (-.5, -.5), (-.5, .5), (.5, .5), (.5, -.5) and I noticed that it appeared squashed in my 800 x 600 window (which seems entirely logical).
I was trying to fix it so that the square appeared square, not rectangular. My approach was to call glOrtho() with values of left = -ar, right = ar, bottom = -1, top = 1 where ar was my aspect ratio (800/600). What I found was that any call I made to glOrtho() had no effect, including the one I was already making (I could remove it and nothing would change).
My understanding of glOrtho() is that it maps the corners of the OpenGL context to the values supplied, and stretches everything between those points to fit. Is that incorrect, or am I doing something that's preventing my call to glOrtho() from taking effect?
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
public class GLOrthoTestDriver {
public static void main(String[] args) {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("glOrtho Test");
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
Display.destroy();
System.exit(1);
}
// Initialization code for OpenGL
glMatrixMode(GL_PROJECTION);
glOrtho(-1, 1, -1, 1, -1, 1);
glLoadIdentity();
// Scene setup
int vertexBufferHandle;
int colorBufferHandle;
FloatBuffer vertexData = BufferUtils.createFloatBuffer(8);
vertexData.put(new float[]
{
-.5f, -.5f,
-.5f, .5f,
.5f, .5f,
.5f, -.5f
}
);
vertexData.flip();
FloatBuffer colorData = BufferUtils.createFloatBuffer(12);
colorData.put(new float[]
{
1, 1, 1,
1, 1, 1,
1, 1, 1,
1, 1, 1
}
);
colorData.flip();
vertexBufferHandle = glGenBuffers();
colorBufferHandle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle);
glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, colorData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while (!Display.isCloseRequested()) {
glClear(GL_COLOR_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glColorPointer(3, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
Display.update();
Display.sync(60);
}
glDeleteBuffers(vertexBufferHandle);
glDeleteBuffers(colorBufferHandle);
Display.destroy();
}
}
Ah - your problem is that you're calling glLoadIdentity after calling glOrtho. glLoadIdentity replaces the matrix in the current mode (GL_PROJECTION) with the identity matrix, thus wiping out any previous call to glOrtho.
Try calling glLoadIdentity before glOrtho.
I'm trying to display a texture with height-field (think kinect here). What I got gives an 0x501 error, no idea why.
So the questions are: why am I getting this 0x501 error? And the rest of the code: should this work?
// void EC(void) is an inline function that checks for OpenGL errors and shows them
// url_width / url_height: dimensions of the frame and by that the dimensions of the texture/height field
// texture_id: id for the coordinates of each point in the texture
// vector_id: id for the vectors which set the x/y and height
// texture_color_id: id for the frame bitmap which is used for colors
// malloc
vertex_coords = new GLfloat[url_width * url_height * 6 * 3];
texture_coords = new GLfloat[url_width * url_height * 6 * 2];
// calculate x/y offsets in texture for each point
int index = 0;
for (int hMapX = 0; hMapX < url_width; hMapX++)
{
for (int hMapY = 0; hMapY < url_height; hMapY++)
{
for (int nTri = 0; nTri < 6; nTri++)
{
int x = (float)hMapX + ((nTri == 1 || nTri == 2 || nTri == 5) ? 1 : 0);
int y = (float)hMapY + ((nTri == 2 || nTri == 4 || nTri == 5) ? 1 : 0);
texture_coords[index++] = (double)x / (double)url_width;
texture_coords[index++] = (double)y / (double)url_height;
}
}
}
// copy texture pointers into videocard
glBindBuffer(GL_ARRAY_BUFFER, texture_id); EC();
int texture_bytes = url_width * url_height * 6 * 2 * sizeof(GLfloat);
glBufferData(GL_ARRAY_BUFFER, texture_bytes, NULL, GL_STATIC_DRAW); EC();
glBufferSubData(GL_ARRAY_BUFFER, 0, texture_bytes, texture_coords); EC();
// pre-initialize vertex structures
glBindBuffer(GL_ARRAY_BUFFER, vertex_id); EC();
int vertex_bytes = url_width * url_height * 6 * 3 * sizeof(GLfloat);
glBufferData(GL_ARRAY_BUFFER, vertex_bytes, NULL, GL_STATIC_DRAW); EC();
// draw function()
/////... fill vertex array with x,y and height in z
//
// copy vertexes to card
int vertex_bytes = url_width * url_height * 6 * 3 * sizeof(GLfloat);
glBindBuffer(GL_ARRAY_BUFFER, vertex_id); EC();
//
// ======> THIS OPENGL CALL FAILS WITH THE 0x501 ERROR <======
//
glBufferSubData(GL_ARRAY_BUFFER, 0, vertex_bytes, vertex_coords); EC();
// copy texture picture into card
glEnable(GL_TEXTURE_2D); EC();
glBindTexture(GL_TEXTURE_2D, texture_colors_id); EC();
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bg -> w, bg -> h, 0, GL_RGBA, GL_UNSIGNED_BYTE, bg -> pixels); EC();
glDisable(GL_TEXTURE_2D); EC();
glEnable(GL_TEXTURE_2D); EC();
glBindTexture(GL_TEXTURE_2D, texture); EC();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Verts
glBindBuffer(GL_ARRAY_BUFFER, vertex_id);
glVertexPointer(3, GL_FLOAT, 0, 0);
// Tex coords
glBindBuffer(GL_ARRAY_BUFFER, texture_id);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertex_id);
// not sure if i should use quads for this
glDrawElements(GL_QUADS, 6, GL_FLOAT, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D); EC();