使用VBO和VBA在LWJGL OpenGL中绘制三角形

时间:2014-03-16 05:31:25

标签: opengl glsl shader lwjgl vbo

我是最新版本的OpenGL的新手,我正在尝试按照本教程学习它:http://open.gl/drawing

然而,我正在使用最新版本的LWJGL,并尽力将其OpenGL用于本教程。仍然,应该绘制的白色三角形不是。

这是我的代码:

package experiments;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;


public class Exp1 {

    //Shader
    private int shaderProgram;
    private int vertShader;
    private int fragShader;

    //Vertex Buffer Object
    private int vbo;

    //Vertex Array Object
    private int vao;

    //Triangle
    private float vertices[] = {
             0.0f,  0.5f, // Vertex 1 (X, Y)
             0.5f, -0.5f, // Vertex 2 (X, Y)
            -0.5f, -0.5f  // Vertex 3 (X, Y)
    };

    public Exp1() throws IOException {
        setUpDisplay();
    }

    private void createShader() throws IOException
    {
        this.shaderProgram = glCreateProgram();
        this.vertShader = glCreateShader(GL_VERTEX_SHADER);
        this.fragShader = glCreateShader(GL_FRAGMENT_SHADER);

        //set source and compile
        glShaderSource(vertShader, fileToString("src/experiments/shader.vert"));
        glCompileShader(vertShader);
        if(glGetShaderi(vertShader, GL_COMPILE_STATUS) == GL_FALSE) System.err.print("Vertex Shader wasn't able to be compiled correctly");

        glShaderSource(fragShader, fileToString("src/experiments/shader.frag"));
        glCompileShader(fragShader);
        if(glGetShaderi(fragShader, GL_COMPILE_STATUS) == GL_FALSE) System.err.print("Fragment Shader wasn't able to be compiled correctly");

        //attach shaders to shader program
        glAttachShader(shaderProgram, vertShader);
        glAttachShader(shaderProgram, fragShader);
        glLinkProgram(shaderProgram);
        glValidateProgram(shaderProgram);
    }

    private void start() throws IOException
    {   
        this.vao = glGenVertexArrays();
        glBindVertexArray(vao);

        this.vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        FloatBuffer fBuffer= ByteBuffer.allocateDirect(vertices.length * 4).asFloatBuffer();
        fBuffer.put(vertices);
        glBufferData(GL_ARRAY_BUFFER, fBuffer, GL_STATIC_DRAW);

        createShader();
        glUseProgram(shaderProgram);

        int posAttrib = glGetAttribLocation(shaderProgram, "position");
        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, false, 0, 0);
        glEnableVertexAttribArray(posAttrib);

        while(!Display.isCloseRequested())
        {
            render();
            Display.update();
            Display.sync(60);
        }
        glDeleteProgram(shaderProgram);
        glDeleteShader(vertShader);
        glDeleteShader(fragShader);
        Display.destroy();
        System.exit(0);

    }

    private void render()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3);
    }

    private String fileToString(String path) throws IOException
    {
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new FileReader(path));

        String line;
        while((line = reader.readLine()) != null)
            builder.append(line).append('\n');

        reader.close();

        return builder.toString();
    }

    private void setUpDisplay()
    {
        try
        {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Shader Demo");
            Display.create();
        }
        catch (LWJGLException e) {
            System.out.println("Display Fail");
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }
    }

    public static void main(String[] args) throws IOException {
        Exp1 demo = new Exp1();
        demo.start();
    }
}

我的着色器与教程完全相同,但是为了更容易阅读,它们会发布它们:

.frag

#version 150

out vec4 outColor;

void main()
{
    outColor = vec4(1.0, 1.0, 1.0, 1.0);
}

.vert

#version 150

in vec2 position;

void main()
{
    gl_Position = vec4(position, 0.0, 1.0);
}

代码运行但都是黑色的。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

我发现了问题:

    FloatBuffer fBuffer= ByteBuffer.allocateDirect(vertices.length * 4).asFloatBuffer();
    fBuffer.put(vertices);
    glBufferData(GL_ARRAY_BUFFER, fBuffer, GL_STATIC_DRAW);

这段代码错了。正确的方法是:

    //Create vertice buffer
    FloatBuffer verticeBuffer= BufferUtils.createFloatBuffer(vertices.length);
    verticeBuffer.put(vertices).flip();

    //Send vertice buffer to VBO
    glBufferData(GL_ARRAY_BUFFER, verticeBuffer, GL_STATIC_DRAW);

以下是整个代码,以防对任何人有用,我尽量使其尽可能可读:)

package experiments;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;


public class Exp1 {

    //Shader
    private int shaderProgram;
    private int vertShader;
    private int fragShader;

    //Vertex Buffer Object
    private int vbo;

    //Vertex Array Object
    private int vao;

    //Triangle
    private float vertices[] = {
         0.0f,  0.5f, // Vertex 1 (X, Y)
         0.5f, -0.5f, // Vertex 2 (X, Y)
        -0.5f, -0.5f  // Vertex 3 (X, Y)
    };
    private int posAttrib;

    public Exp1() throws IOException {
        setUpDisplay();
    }

    private void start() throws IOException
    {   
        setUpDraw();

        while(!Display.isCloseRequested())
        {
            render();
            Display.update();
            Display.sync(60);
        }

        glDeleteProgram(shaderProgram);
        glDeleteShader(vertShader);
        glDeleteShader(fragShader);

        glDeleteBuffers(vbo);
        glDeleteVertexArrays(vao);

        Display.destroy();
        System.exit(0);
    }

    private void setUpDraw() throws IOException{
        // Create a new VAO in memory and bind it (A VAO can have up to 16 attributes (VBO's) assigned to it by default)
        this.vao = glGenVertexArrays();
        glBindVertexArray(vao);

        //Create a new VBO in memory and bind it (A VBO is a collection of Vectors which in this case resemble the location of each vertex)
        this.vbo = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, vbo);

        //Create new shader and use it
        createShader();
        glUseProgram(shaderProgram);

        //Create vertice buffer
        FloatBuffer verticeBuffer= BufferUtils.createFloatBuffer(vertices.length);
        verticeBuffer.put(vertices).flip();

        //Send vertice buffer to VBO
        glBufferData(GL_ARRAY_BUFFER, verticeBuffer, GL_STATIC_DRAW);

        //Put the VBO in the attributes list at index posAttrib
        posAttrib = glGetAttribLocation(shaderProgram, "position");
        glVertexAttribPointer(posAttrib, 2, GL_FLOAT, false, 0, 0);

        //Unbind VBO and VAO
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    }

    private void createShader() throws IOException
    {
        //create
        this.shaderProgram = glCreateProgram();
        this.vertShader = glCreateShader(GL_VERTEX_SHADER);
        this.fragShader = glCreateShader(GL_FRAGMENT_SHADER);

        //set source and compile
        glShaderSource(vertShader, fileToString("src/experiments/shader.vert"));
        glCompileShader(vertShader);
        if(glGetShaderi(vertShader, GL_COMPILE_STATUS) == GL_FALSE) System.err.print("Vertex Shader wasn't able to be compiled correctly");

        glShaderSource(fragShader, fileToString("src/experiments/shader.frag"));
        glCompileShader(fragShader);
        if(glGetShaderi(fragShader, GL_COMPILE_STATUS) == GL_FALSE) System.err.print("Fragment Shader wasn't able to be compiled correctly");

        //attach shaders to shader program
        glAttachShader(shaderProgram, vertShader);
        glAttachShader(shaderProgram, fragShader);
        glLinkProgram(shaderProgram);
        glValidateProgram(shaderProgram);
    }

    private void render()
    {
        //Clear screen
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        //Bind our VAO which already has the quad info and enable attribute list in posAttrib index
        glBindVertexArray(vao);
        glEnableVertexAttribArray(posAttrib);

        //Draw the vertices
        glDrawArrays(GL_TRIANGLES, 0, 3);

        //Unbind back to defaults
        glDisableVertexAttribArray(posAttrib);
        glBindVertexArray(0);
    }

    private String fileToString(String path) throws IOException
    {
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new FileReader(path));

        String line;
        while((line = reader.readLine()) != null)
            builder.append(line).append('\n');

        reader.close();

        return builder.toString();
    }

    private void setUpDisplay()
    {
        try
        {
            Display.setDisplayMode(new DisplayMode(640, 480));
            Display.setTitle("Shader Demo");
            Display.create();
        }
        catch (LWJGLException e) {
            System.out.println("Display Fail");
            e.printStackTrace();
            Display.destroy();
            System.exit(1);
        }
    }

    public static void main(String[] args) throws IOException {
        Exp1 demo = new Exp1();
        demo.start();
    }
}

答案 1 :(得分:0)

您正在检查着色器编译日志,因此着色器应该没问题。开始调试这些的一个好方法是开始在很多地方插入glGetError()个调用。如果您获得非零返回值(0 == GL_NO_ERROR),您就会发现早期gl*来电出现问题。目前,例如,您正在调用glValidateProgram,如果程序未成功链接,则会生成错误,但您必须自己使用glGetError()检查错误。

编辑:由于您正在使用LWJGL,您还可以使用lwjgl.opengl.Util中的错误检查方法。