I am new in with Java OpenGL (JOGL). I want to display a 3D cube in JOGL.
I have vertex array information with me.
double vertices[]= {
0 0 0,
0 0 1,
0 1 0,
0 1 1,
1 0 0,
1 0 1,
1 1 0,
1 1 1,
};
I want to use glDrawArrays() to display it. Since I have display a model having a huge amount of vertices.
The display method is given below.
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glBegin(GL_TRIANGLE_STRIP);
gl.glEnd();
}
I need to use GL_TRIANGLES or GL_TRIANGLE_STRIP only and not GL_QUADS.
If anyone knows how to use glDrawArrays(); in JOGL please help me. I want JOGL syntax and not opengl.
If you want to use glDrawArrays(); then you have to create a VBO (Vertex Buffer Objects) or a VA (Vertex Arrays). If you're after speed, then choose VBO, though they require some extra lines of code to be made!
The best way I think I can explain how to create a VBO to you, is by giving you an example!
VBO Example
Here is a little example of a VBO storing Vertices and Colors for a Triangle and rendering it and also how to delete it!
Creating the VBO
This is the code where you create the actual Vertex and Color Buffer and bind them to the VBO.
int vertices = 3;
int vertex_size = 3; // X, Y, Z,
int color_size = 3; // R, G, B,
FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * vertex_size);
vertex_data.put(new float[] { -1f, -1f, 0f, });
vertex_data.put(new float[] { 1f, -1f, 0f, });
vertex_data.put(new float[] { 1f, 1f, 0f, });
vertex_data.flip();
FloatBuffer color_data = BufferUtils.createFloatBuffer(vertices * color_size);
color_data.put(new float[] { 1f, 0f, 0f, });
color_data.put(new float[] { 0f, 1f, 0f, });
color_data.put(new float[] { 0f, 0f, 1f, });
color_data.flip();
int vbo_vertex_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int vbo_color_handle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
glBufferData(GL_ARRAY_BUFFER, color_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
You can of course add more Vertices and Colors to the vertex_data and color_data if you want to! But always remember that the amount of vertex data, need to match with the amount of color data and vice versa!
Important: Only create the VBO(s) once, and only update them when necessary! Don't create them for each frame, since them you will end up with a frame-rate worse than when using immediate mode for rendering!
Rendering the VBO
This is the code you need to call, to render the VBO.
glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
glVertexPointer(vertex_size, GL_FLOAT, 0, 0l);
glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
glColorPointer(color_size, GL_FLOAT, 0, 0l);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glDrawArrays(GL_TRIANGLES, 0, vertices);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
Deleting the VBO
Then when you're done with the VBO and you don't need it anymore, you can delete it by doing the following.
glDeleteBuffers(vbo_vertex_handle);
glDeleteBuffers(vbo_color_handle);
Related
I am trying to draw a simple, red triangle on screen. Without using an VBO the code works as intended. When trying to draw it by using an VBO (with or without shader), it simply has no effect.
My code:
//Works
glBegin(GL_TRIANGLES);
glVertex3f(0f, 0f, 0.0f);
glVertex3f(0.5f, 0f, 0.0f);
glVertex3f(0.5f, 0.5f, 0.0f);
glEnd();
//Does not work
int vertexArrayID = glGenVertexArrays();
glBindVertexArray(vertexArrayID);
float[] g_vertex_buffer_data = new float[]{
0f, 0f, 0.0f,
0.5f, 00f, 0.0f,
0.5f, 0.5f, 0.0f,
};
int vertexbuffer = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, FloatBuffer.wrap(g_vertex_buffer_data), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
false, // normalized?
0, // stride
0 // array buffer offset
);
glDrawArrays(GL_TRIANGLES, 0, 3); // 3 indices starting at 0 -> 1 triangle
glDisableVertexAttribArray(0);
glDeleteBuffers(vertexbuffer);
glDeleteVertexArrays(vertexArrayID);
System.out.println(glGetError());
glGetError() always returns 0.
I use a default, tutorial-copied shader to test my code (I link and bind the program before using above code):
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(){
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
#version 330 core
// Ouput data
out vec3 color;
void main()
{
// Output color = red
color = vec3(1,0,0);
}
I want to draw a rectangle in lwjgl. The code should draw a rectangle, but it doesn't. I am using OpenGL 4.4 (LWJGL doesn't support beyond that). I am mostly a beginner in 3d Graphics and such so any help would be greatly appreciated.
float[] vertices= {
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
float[] indices= {
0,1,2,
2,3,0
};
Shader vsh=new Shader("vertexShader.vsh",GL_VERTEX_SHADER);
Shader fsh=new Shader("fragmentShader.fsh",GL_FRAGMENT_SHADER);
sp=Shader.createProgram(vsh.shader,fsh.shader);
int VBO,EBO;
VAO=glGenVertexArrays();
VBO=glGenBuffers();
EBO=glGenBuffers();
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,indices,GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
glClearColor(1.0f,1.0f,1.0f,1.0f);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
void loop(){
while(!glfwWindowShouldClose(w.window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(sp);
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
glfwSwapBuffers(w.window);
glfwPollEvents();
}
}
void run() {
init();
loop();
}
public static void main(String[] args) {
new Core().run();
}
It works when I remove the indices and use glDrawArrays instead of glDrawElements.
The type of the array of indices has to be int rather than float:
float[] indices =
int [] indices =
The type of the data in the element array buffer has to match the which is specified when glDrawElements is called.
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,0);
The specified type must be one of GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, or GL_UNSIGNED_INT. The corresponding data types in java are byte, short respectively int.
Ive been playing around with open GL for a while now and i got to the point that i can draw 3d shapes, My shapes and vertices and indices are definitely right and my shape was getting messed up. I am now wanting to redo my drawing. I used to only use VBO with no VAO and just bind and draw them. This worked but im suspicious of this being my bug. So i started using VAO's and i dont see anything that is wrong with my code and i still cant get it to draw my white square(no shaders just like the wiki tutorials).
My code for initializing the window is here:
private void initWindow() {
//Makes sure window can work
if (!glfwInit()) {
throw new IllegalStateException("Failed to Initialize GLFW!");
}
//Create window object and set its hints
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
this.windowRef = glfwCreateWindow(width, height, name, NULL, NULL);
if (windowRef == 0) {
throw new IllegalStateException("Failed to create Window!");
}
GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(windowRef, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2);
// Make the OpenGL context current
glfwMakeContextCurrent(windowRef);
// Enable v-sync
glfwSwapInterval(1);
//Make GL capabilites for window
GL.createCapabilities();
glfwShowWindow(windowRef);
}
my code for initializing my buffers and objects is here
public void loadGL() {
float[] vertex = {
0f, 0f, 0f, //0
0.5f, 0, 0, //1
0.5f, 0, 0.5f, //2
0f, 0f, 0.5f, //3
0f, 0.5f, 0f, //4
0.5f, 0.5f, 0, //5
0.5f, 0.5f, 0.5f,//6
0f, 0.5f, 0.5f//7
};
int[] index = {
0, 1, 2, //0
0, 2, 3, //1
0, 3, 4, //2
3, 7, 4,//3
0, 4, 1,//4
1, 5, 4,//5
1, 5, 2,//6
2, 6, 5,//7
2, 3, 6,//8
3, 7, 6,//9
4, 5, 7,//10
5, 6, 7//11
};
size = 12*3;
indicesBuff = BufferUtils.createIntBuffer(index.length);
vertBuff = BufferUtils.createFloatBuffer(vertex.length);
indicesBuff.put(index);
vertBuff.put(vertex);
indicesBuff.flip();
vertBuff.flip();
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
and finally my main loop is here, it is called after the window init:
private void mainLoop() {
loadGL();
glClearColor(0.5f, 0.5f, 0.5f, 1);
while (!glfwWindowShouldClose(windowRef)) {
//Render Stuff here
//TODO: later skip this block if nothing has changed
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear
the framebuffer
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
// glBegin(GL_QUADS);
// glVertex3f(-0.5f, -0.5f, 0);
// glVertex3f(-0.5f, 0.5f, 0);
// glVertex3f(0.5f, -0.5f, 0);
// glVertex3f(0.5f, 0.5f, 0);
// glEnd();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glfwSwapBuffers(windowRef);
glfwPollEvents();
}
}
btw drawing it with glBegin and so works but its not efficient for what i want to do.
The modern way of rendering in OpenGL, would be to use a Shader program.
If you don't use a shader program, than you have to define the array of vertex data using the deprected way by glVertexPointer and you have to enable the client-side capability for vertex coordinates by glEnableClientState( GL_VERTEX_ARRAY ):
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(vao);
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableClientState( GL_VERTEX_ARRAY ); // <---------------
glBindVertexArray(0);
Further note, that the state of the client-side capability (or vertex attribute array) and the reference to the index (element) buffer is stored in the Vertex Array Objects state vector.
So it is sufficient to enable the vertex coordinates, when the vertex array object is specified and to bid the index buffer when the vertex array object is bound. The enabling and disabling of the vertex coordinates and binding of the index buffer, when drawing the geometry, can be omitted:
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vertBuff, GL_STATIC_DRAW);
GL20.glVertexPointer(3, GL_FLOAT, 0, 0); // <--------------
glEnableClientState( GL_VERTEX_ARRAY ); // <--------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuff, GL_STATIC_DRAW);
// skip glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
so i want to draw a shape using VAO and VBOs and i think im doing everything right but whenever i run my code i just get the window with the clear color. I had an issue before when i tried to initialize the triangles before i called create capabilities, am i missing some function to start drawing?
here is my code:
int vaoId, vboId, vertexCount;
float[] vertices = {
// Left bottom triangle
-0.5f, 0.5f,
-0.5f, -0.5f,
0.5f, -0.5f,};
private void init() {
if (!glfwInit()) {
throw new IllegalStateException("Failed to Initialize GLFW!");
}
int width = 1000;
int height = 1000;
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
window = glfwCreateWindow(width, height, "App", NULL, NULL);
if (window == 0) {
throw new IllegalStateException("Failed to create Window!");
}
GLFWVidMode videoMode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, (videoMode.width() - width) / 2, (videoMode.height() - height) / 2);
// Make the OpenGL context current
glfwMakeContextCurrent(window);
// Enable v-sync
glfwSwapInterval(1);
glfwShowWindow(window);
}
private void loop() {
// This line is critical for LWJGL's interoperation with GLFW's
// OpenGL context, or any context that is managed externally.
// LWJGL detects the context that is current in the current thread,
// creates the GLCapabilities instance and makes the OpenGL
// bindings available for use.
GL.createCapabilities();
initTriangle();
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT); // clear the framebuffer
glBindVertexArray(vaoId);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glDisableVertexAttribArray(0);
glBindVertexArray(0);
glfwSwapBuffers(window); // swap the color buffers
// Poll for window events. The key callback above will only be
// invoked during this call.
glfwPollEvents();
}
}
private void initTriangle() {
FloatBuffer vertBuf = MemoryUtil.memAllocFloat(vertices.length);
vertBuf.put(vertices);
vertBuf.flip();
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertBuf, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
I hope you guys can help, thanks a lot.
I am not using shaders. Is that my problem? And is it a necessity
The state of the art way of rendering in OpenGL, would be to use a Shader.
If you don't use a shader, than you have to define the array of vertex data by glVertexPointer
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertBuf, GL_STATIC_DRAW);
glVertexPointer( 2, GL_FLOAT, 0, 0 ); // <---------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
and you have to enable the client-side capability for vertex coordinates by glEnableClientState( GL_VERTEX_ARRAY ):
glBindVertexArray(vaoId);
glEnableClientState( GL_VERTEX_ARRAY ); // <---------------
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glDisableClientState( GL_VERTEX_ARRAY ); // <---------------
glBindVertexArray(0);
Note, this state of the client-side capability (or vertex attribute array) is stored in the Vertex Array Object.
So it is sufficient to enable the vertex coordinates, when the vertex array object is specified. The enabling and disabling of the vertex coordinates, when drawing the geometry, can be omitted:
vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertBuf, GL_STATIC_DRAW);
glVertexPointer( 2, GL_FLOAT, 0, 0 );
glEnableClientState( GL_VERTEX_ARRAY ); // <---------------
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLES, 0, vertexCount);
glBindVertexArray(0);
a friend and I are currently working on some LWJGL 2D related things. I was working on VBOs and was able to get it to work. Now when using this to draw tiles, they work. however, my FPS drops significantly. Perhaps I'm doing something wrong.
Here's my code.
public void drawTextureRect(float x, float y, float width, float height,
String textureName) {
// Bind the texture to draw
texture = loadTexture(textureName);
texture.bind();
// Set triangle vertex data
FloatBuffer vertices = BufferUtils.createFloatBuffer(6);
vertices.put(new float[] { x, y, x + width, y, x, height + y });
// Set texture coordinates
FloatBuffer textcoord = BufferUtils.createFloatBuffer(6);
textcoord.put(new float[] { 0, 0, 1, 0, 0, 1 });
// Allow OpenGL to interpret the Text Coordinates & Vertex Data
textcoord.flip();
vertices.flip();
int VertexHandle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, VertexHandle);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int TextureHandle = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, TextureHandle);
glBufferData(GL_ARRAY_BUFFER, textcoord, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VertexHandle);
glVertexPointer(2, GL_FLOAT, 0, 0L);
glBindBuffer(GL_ARRAY_BUFFER, TextureHandle);
glTexCoordPointer(2, GL_FLOAT, 0, 0L);
// Enable Vertex and Texture Arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Draw Triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
// Unable Vertex and Textures
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
/* SECOND TRIANGLE */
// Set Second Triangle Coordinates
FloatBuffer vertices2 = BufferUtils.createFloatBuffer(6);
vertices2.put(new float[] { x + width, y + height, x, height + y,
x + width, y });
// Set Second Texture Coordinates
FloatBuffer textcoord2 = BufferUtils.createFloatBuffer(6);
textcoord2.put(new float[] { 1, 1, 0, 1, 1, 0 });
// Allow OpenGl to interpret the Text Coordinates & Vertex Data
textcoord2.flip();
vertices2.flip();
int VertexHandle2 = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, VertexHandle2);
glBufferData(GL_ARRAY_BUFFER, vertices2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
int TexCord = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, TexCord);
glBufferData(GL_ARRAY_BUFFER, textcoord2, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, VertexHandle2);
glVertexPointer(2, GL_FLOAT, 0, 0L);
glBindBuffer(GL_ARRAY_BUFFER, TexCord);
glTexCoordPointer(2, GL_FLOAT, 0, 0L);
// Enable Vertex and Texture Arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Draw Triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
// Unable Vertex and Textures
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDeleteBuffers(TextureHandle);
glDeleteBuffers(TexCord);
glDeleteBuffers(VertexHandle);
glDeleteBuffers(VertexHandle2);
}`