问题
3I have the following SceneRenderer class, implementing GLEventListener. I think I understand the process of creating buffers, storing pointers to those buffers and filling those buffers with data (see init method).
Where I struggle is the display() method. I've tried almost every combination of EVERYTHING i found on the internet and I'm still not able to draw anything. Could someone explain me what to do now, with all the buffers filled with data waiting to be rendered ?
package cz.pscheidl.gui;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
public class SceneRenderer implements GLEventListener {
private IntBuffer buffers = IntBuffer.allocate(2);
private float[] square = {
-1.0f, -1.0f,
1.0f, -1.0f,
1.0f, 1.0f,
1.0f, 1.0f,
-1.0f, 1.0f,
-1.0f, -1.0f,
};
private float[] colorData = {
255, 0, 0,
255, 255, 0,
0, 255, 0,
0, 255, 0,
0, 0, 255,
255, 0, 0
};
FloatBuffer vertexFB = FloatBuffer.wrap(square);
FloatBuffer colorFB = FloatBuffer.wrap(colorData);
GLU glu = new GLU();
@Override
public void init(GLAutoDrawable glAutoDrawable) {
GL3 gl = glAutoDrawable.getGL().getGL3();
gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
gl.glEnable(GL2.GL_DEPTH_TEST);
gl.glClearDepthf(10.0f);
gl.glClearColor(0.8f, 0.6f, 0.8f, 1.0f);
gl.glDepthFunc(GL2.GL_LEQUAL);
gl.glGenBuffers(2, buffers);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(0));
gl.glBufferData(GL2.GL_ARRAY_BUFFER, 4 * 6 * 2, vertexFB, GL3.GL_STATIC_DRAW);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(1));
gl.glBufferData(GL2.GL_ARRAY_BUFFER, 4 * 6 * 3, colorFB, GL2.GL_STREAM_DRAW);
}
@Override
public void dispose(GLAutoDrawable glAutoDrawable) {
}
@Override
public void display(GLAutoDrawable glAutoDrawable) {
GL3 gl = glAutoDrawable.getGL().getGL3();
gl.glClear(GL3.GL_DEPTH_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, buffers.get(0));
//After binding the buffer, now WHAT ?
}
@Override
public void reshape(GLAutoDrawable glAutoDrawable, int i, int i2, int i3, int i4) {
GL3 gl = glAutoDrawable.getGL().getGL3();
glu.gluPerspective(80.0f, 1920.0f / 1080.0f, 0.1f, 100f);
}
}
回答1:
There are a couple things you are missing:
1. Shaders
Shaders are programs that run on the gpu. This is how you tell the gpu what to do with your data. This is how you would create a very basic Program that has a Vertex and Fragment Shader, that would display your mesh.
Put this up with your class level var declarations:
private int program;
This would go inside your init() function:
// Create program.
program = gl.glCreateProgram();
// Create vertexShader.
int vertexShader = gl.glCreateShader(GL2ES2.GL_VERTEX_SHADER);
String[] vertexShaderSource = new String[1];
vertexShaderSource[0] = "#version 330\n" +
"layout(location=0) in vec2 position;\n" +
"layout(location=1) in vec3 color;\n" +
"out vec3 vColor;\n" +
"void main(void)\n" +
"{\n" +
"gl_Position = vec4(position, 0.0, 1.0);\n"
"vColor = vec4(color, 1.0);\n"
"}\n";
gl.glShaderSource(vertexShader, 1, vertexShaderSource, null);
gl.glCompileShader(vertexShader);
// Create and fragment shader.
int fragmentShader = gl.glCreateShader(GL2ES2.GL_FRAGMENT_SHADER);
String[] fragmentShaderSource = new String[1];
fragmentShaderSource[0] = "#version 330\n" +
"in vec4 vColor;\n" +
"out vec4 fColor;\n" +
"void main(void)\n" +
"{\n" +
"fColor = vColor;\n" +
"}\n";
gl.glShaderSource(fragmentShader, 1, fragmentShaderSource, null);
gl.glCompileShader(fragmentShader);
// Attach shaders to program.
gl.glAttachShader(program, vertexShader);
gl.glAttachShader(program, fragmentShader);
gl.glLinkProgram(program);
2. Vertex Array
You have two buffers that need to be used when you draw. A Vertex Array allows you to store the state of multiple buffers and to send the data to different locations in your shader program.
Put this with your class level var declarations:
IntBuffer vertexArray = IntBuffer.allocate(1);
This would also go in your init() function, after you create the buffers:
// Create Vertex Array.
gl.glGenVertexArrays(1, vertexArray);
gl.glBindVertexArray(vertexArray.get(0));
// Specify how data should be sent to the Program.
// VertexAttribArray 0 corresponds with location 0 in the vertex shader.
gl.glEnableVertexAttribArray(0);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(0));
gl.glVertexAttribPointer(0, 2, GL.GL_FLOAT, false, 0, 0);
// VertexAttribArray 1 corresponds with location 1 in the vertex shader.
gl.glEnableVertexAttribArray(1);
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, buffers.get(1));
gl.glVertexAttribPointer(1, 3, GL.GL_FLOAT, false, 0, 0);
Your display() function should now look like this:
@Override
public void display(GLAutoDrawable glAutoDrawable) {
GL3 gl = glAutoDrawable.getGL().getGL3();
gl.glClear(GL3.GL_DEPTH_BUFFER_BIT | GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(program)
gl.glBindVertexArray(vertexArray.get(0));
gl.glDrawArrays(GL.GL_TRIANGLES, 0, 6)
}
Miscellaneous notes:
-Your color values should range from 0 to 1, not 0 to 255.
-You should research destroying the OpenGL objects you create, for when the program closes or you no longer need them.
-I highly recommend reading these tutorials: OpenGL Book and Learning Modern 3D Graphics Programming. The code examples are in C++ but I found them extremely helpful.
来源:https://stackoverflow.com/questions/17630753/jogl-opengl-vbo-how-to-render-vertices