I am building OPENGL application in Java using lwjgl and following part of tutorial on YouTube by thebennybox
I am able to create rectangle using Mesh class i build.
import engine.core.Util;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
public class Mesh {
private int vbo;
private int size;
public Mesh() {
this.vbo = glGenBuffers();
this.size = 0;
}
public void addVertices(Vertex[] vertices){
this.size = vertices.length * Vertex.SIZE;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);
}
public void draw(){
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glDrawArrays(GL_TRIANGLES, 0, this.size);
glDisableVertexAttribArray(0);
}
}
And util
helper
import engine.render.Vertex;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
public class Util {
public static FloatBuffer createFloatBuffer(int size){
return BufferUtils.createFloatBuffer(size);
}
public static FloatBuffer createFlippedBuffer(Vertex[] vertices){
FloatBuffer buffer = createFloatBuffer(vertices.length * Vertex.SIZE);
for(int i = 0; i < vertices.length; i++) {
buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
}
buffer.flip();
return buffer;
}
}
Here is how i am rendering
this.mesh = new Mesh();
Vertex[] data = new Vertex[]{
//1st triangle
new Vertex(new Vector3(0.5f,-0.5f,0)), //RB
new Vertex(new Vector3(-0.5f,-0.5f,0)), //LB
new Vertex(new Vector3(0.5f,0.5f,0)), //RT
//2nd triangle
new Vertex(new Vector3(-0.5f,0.5f,0)), //RB
new Vertex(new Vector3(0.5f,0.5f,0)), //RT
new Vertex(new Vector3(-0.5f,-0.5f,0)), //LB
};
mesh.addVertices(data);
public void render(){ //update per frame
mesh.draw();
}
So far it worked. Then I followed tutorial for shader and got error
Validation Failed: No vertex array object bound.
Here is shader class
import static org.lwjgl.opengl.GL32C.*;
public class Shader {
private int program;
public Shader() {
program = glCreateProgram();
if(program == 0){
System.out.println("Shader creation failed!");
System.exit(1);
}
}
public void addVertexShader(String text){
//System.out.println(text);
addProgram(text, GL_VERTEX_SHADER);
}
public void addGeometryShader(String text){
addProgram(text, GL_GEOMETRY_SHADER);
}
public void addFragmentShader(String text){
addProgram(text, GL_FRAGMENT_SHADER);
}
public void bind(){
glUseProgram(program);
}
public void compileShader(){
glLinkProgram(program);
if(glGetProgrami(program, GL_LINK_STATUS) == 0){
System.out.println(glGetProgramInfoLog(program, 1024));
System.exit(1);
}
glValidateProgram(program);
if(glGetProgrami(program, GL_VALIDATE_STATUS) == 0){
// System.out.println("ffff");
System.out.println( glGetProgramInfoLog(program, 1024));
System.exit(1);
}
}
public void addProgram(String text, int type){
int shader = glCreateShader(type);
if(shader == 0){
System.out.println("Shader creation failed!");
System.exit(1);
}
glShaderSource(shader, text);
glCompileShader(shader);
if(glGetShaderi(shader, GL_COMPILE_STATUS) == 0){
System.out.println(glGetShaderInfoLog(shader, 1024));
System.exit(1);
}
glAttachShader(program, shader);
}
}
And here is ResourceLoader
import java.io.BufferedReader;
import java.io.FileReader;
public class ResourceLoader {
public static String loadShader(String fileName){
StringBuilder shaderSource = new StringBuilder();
BufferedReader shaderReader = null;
try {
shaderReader = new BufferedReader(new FileReader(fileName));
String line;
while ((line = shaderReader.readLine()) != null){
shaderSource.append(line).append("\n");
}
} catch (Exception e){
System.out.println(e.getMessage());
}
return shaderSource.toString();
}
}
GLSL CODE FOR BOTH FILE
==== basicVertex.glsl
#version 410 core
out vec4 outColor;
void main(){
outColor = vec4(0.0, 1.0, 1.0, 1.0);
}
========= basicFragment.glsl
#version 410 core
layout (location = 0) in vec3 position;
void main(){
gl_Position = vec4(position, 1.0);
}
You've to create and use a Vertex Array Object.
The Vertex Array Object stores the specification of the arrays of generic vertex attribute data.
Create and bind the VAO when you specify the vertex arrays.e.g:
public class Mesh {
private int vao;
private int vbo;
private int size;
public Mesh() {
this.size = 0;
this.vao = glGenVertexArrays();
this.vbo = glGenBuffers();
glBindVertexArray(this.vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
}
// [...]
}
And use it when you draw the geometry:
public class Mesh {
// [...]
public void draw(){
glBindVertexArray(this.vao);
glDrawArrays(GL_TRIANGLES, 0, this.size);
glBindVertexArray(0); // <--- Note, this is not needed
}
}