使用着色器的程序旋转多维数据集不起作用

时间:2019-03-10 08:30:33

标签: opengl lwjgl

在翻译OpenGL SuperBible 7th Ed中的旋转多维数据集示例应用程序时。我遇到了障碍。我认为这与我如何提供顶点数据有关,因为多维数据集根本没有显示。

搜索“ vao = glGenVertexArrays();”行找出我认为相关部分从哪里开始。

以下为完整程序。另外,这里是github spinning cube上此程序的链接。这是我要翻译的版本的链接:OpenGL Supper bible "spinnycube"

package com.openglsb;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Scanner;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.lwjgl.BufferUtils;
import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.GLFW_FALSE;
import static org.lwjgl.glfw.GLFW.GLFW_KEY_ESCAPE;
import static org.lwjgl.glfw.GLFW.GLFW_RELEASE;
import static org.lwjgl.glfw.GLFW.GLFW_RESIZABLE;
import static org.lwjgl.glfw.GLFW.GLFW_TRUE;
import static org.lwjgl.glfw.GLFW.GLFW_VISIBLE;
import static org.lwjgl.glfw.GLFW.glfwCreateWindow;
import static org.lwjgl.glfw.GLFW.glfwDefaultWindowHints;
import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwGetPrimaryMonitor;
import static org.lwjgl.glfw.GLFW.glfwGetVideoMode;
import static org.lwjgl.glfw.GLFW.glfwGetWindowSize;
import static org.lwjgl.glfw.GLFW.glfwInit;
import static org.lwjgl.glfw.GLFW.glfwMakeContextCurrent;
import static org.lwjgl.glfw.GLFW.glfwPollEvents;
import static org.lwjgl.glfw.GLFW.glfwSetErrorCallback;
import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
import static org.lwjgl.glfw.GLFW.glfwSetWindowPos;
import static org.lwjgl.glfw.GLFW.glfwSetWindowShouldClose;
import static org.lwjgl.glfw.GLFW.glfwShowWindow;
import static org.lwjgl.glfw.GLFW.glfwSwapBuffers;
import static org.lwjgl.glfw.GLFW.glfwSwapInterval;
import static org.lwjgl.glfw.GLFW.glfwTerminate;
import static org.lwjgl.glfw.GLFW.glfwWindowHint;
import static org.lwjgl.glfw.GLFW.glfwWindowShouldClose;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import static org.lwjgl.opengl.GL11.GL_COLOR;
import static org.lwjgl.opengl.GL11.GL_CULL_FACE;
import static org.lwjgl.opengl.GL11.GL_CW;
import static org.lwjgl.opengl.GL11.GL_DEPTH;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_FLOAT;
import static org.lwjgl.opengl.GL11.GL_LEQUAL;
import static org.lwjgl.opengl.GL11.GL_TRIANGLES;
import static org.lwjgl.opengl.GL11.GL_VERSION;
import static org.lwjgl.opengl.GL11.glDepthFunc;
import static org.lwjgl.opengl.GL11.glDrawArrays;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glFrontFace;
import static org.lwjgl.opengl.GL11.glGetString;
import static org.lwjgl.opengl.GL11.glViewport;
import org.lwjgl.opengl.GL15;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL20.GL_COMPILE_STATUS;
import static org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER;
import static org.lwjgl.opengl.GL20.GL_LINK_STATUS;
import static org.lwjgl.opengl.GL20.GL_VALIDATE_STATUS;
import static org.lwjgl.opengl.GL20.GL_VERTEX_SHADER;
import static org.lwjgl.opengl.GL20.glAttachShader;
import static org.lwjgl.opengl.GL20.glCompileShader;
import static org.lwjgl.opengl.GL20.glCreateProgram;
import static org.lwjgl.opengl.GL20.glCreateShader;
import static org.lwjgl.opengl.GL20.glDeleteProgram;
import static org.lwjgl.opengl.GL20.glDeleteShader;
import static org.lwjgl.opengl.GL20.glEnableVertexAttribArray;
import static org.lwjgl.opengl.GL20.glGetProgramInfoLog;
import static org.lwjgl.opengl.GL20.glGetProgrami;
import static org.lwjgl.opengl.GL20.glGetShaderInfoLog;
import static org.lwjgl.opengl.GL20.glGetShaderi;
import static org.lwjgl.opengl.GL20.glGetUniformLocation;
import static org.lwjgl.opengl.GL20.glLinkProgram;
import static org.lwjgl.opengl.GL20.glShaderSource;
import static org.lwjgl.opengl.GL20.glUniformMatrix4fv;
import static org.lwjgl.opengl.GL20.glUseProgram;
import static org.lwjgl.opengl.GL20.glValidateProgram;
import static org.lwjgl.opengl.GL20.glVertexAttribPointer;
import static org.lwjgl.opengl.GL30.glBindVertexArray;
import static org.lwjgl.opengl.GL30.glClearBufferfv;
import static org.lwjgl.opengl.GL30.glDeleteVertexArrays;
import static org.lwjgl.opengl.GL30.glGenVertexArrays;
import org.lwjgl.system.MemoryStack;
import static org.lwjgl.system.MemoryStack.stackPush;
import static org.lwjgl.system.MemoryUtil.NULL;

public class Ch5SpinningCube {

    public static void main(String[] args) {
        Ch5SpinningCube app = new Ch5SpinningCube();
        app.run();
    }

    private long window;
    private int program;
    private int vao;
    private int buffer;
    private int mv_location;
    private int proj_location;
    //private float aspect;
    private final FloatBuffer proj_matrix = BufferUtils.createFloatBuffer(16);

    static float vertex_positions[]
            = {
                -0.25f, 0.25f, -0.25f,
                -0.25f, -0.25f, -0.25f,
                0.25f, -0.25f, -0.25f,
                0.25f, -0.25f, -0.25f,
                0.25f, 0.25f, -0.25f,
                -0.25f, 0.25f, -0.25f,
                0.25f, -0.25f, -0.25f,
                0.25f, -0.25f, 0.25f,
                0.25f, 0.25f, -0.25f,
                0.25f, -0.25f, 0.25f,
                0.25f, 0.25f, 0.25f,
                0.25f, 0.25f, -0.25f,
                0.25f, -0.25f, 0.25f,
                -0.25f, -0.25f, 0.25f,
                0.25f, 0.25f, 0.25f,
                -0.25f, -0.25f, 0.25f,
                -0.25f, 0.25f, 0.25f,
                0.25f, 0.25f, 0.25f,
                -0.25f, -0.25f, 0.25f,
                -0.25f, -0.25f, -0.25f,
                -0.25f, 0.25f, 0.25f,
                -0.25f, -0.25f, -0.25f,
                -0.25f, 0.25f, -0.25f,
                -0.25f, 0.25f, 0.25f,
                -0.25f, -0.25f, 0.25f,
                0.25f, -0.25f, 0.25f,
                0.25f, -0.25f, -0.25f,
                0.25f, -0.25f, -0.25f,
                -0.25f, -0.25f, -0.25f,
                -0.25f, -0.25f, 0.25f,
                -0.25f, 0.25f, -0.25f,
                0.25f, 0.25f, -0.25f,
                0.25f, 0.25f, 0.25f,
                0.25f, 0.25f, 0.25f,
                -0.25f, 0.25f, 0.25f,
                -0.25f, 0.25f, -0.25f
            };

    private void init() {
        GLFWErrorCallback.createPrint(System.err).set();
        if (!glfwInit()) {
            throw new IllegalStateException("Unable to initialize GLFW");
        }
        // Configure GLFW
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        // Create the window
        window = glfwCreateWindow(300, 300, "Hello World!", NULL, NULL);
        if (window == NULL) {
            throw new RuntimeException("Failed to create the GLFW window");
        }

        // Setup a key callback. It will be called every time a key is pressed, repeated or released.
        glfwSetKeyCallback(window, (window, key, scancode, action, mods) -> {
            if (key == GLFW_KEY_ESCAPE && action == GLFW_RELEASE) {
                glfwSetWindowShouldClose(window, true); // We will detect this in the rendering loop
            }
        });

        // Get the thread stack and push a new frame
        try (MemoryStack stack = stackPush()) {
            IntBuffer pWidth = stack.mallocInt(1); // int*
            IntBuffer pHeight = stack.mallocInt(1); // int*
            glfwGetWindowSize(window, pWidth, pHeight);// Get the window size passed to glfwCreateWindow
            GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor()); // Get the resolution of the primary monitor
            glfwSetWindowPos(// Center the window
                    window,
                    (vidmode.width() - pWidth.get(0)) / 2,
                    (vidmode.height() - pHeight.get(0)) / 2
            );
        } // the stack frame is popped automatically

        glfwMakeContextCurrent(window);// Make the OpenGL context current
        glfwSwapInterval(1);        // Enable v-sync

        // Make the window visible
        glfwShowWindow(window);
        GL.createCapabilities();//Critical
        System.out.println("OpenGL Verion: " + glGetString(GL_VERSION));
        this.compileShader();

        mv_location = glGetUniformLocation(program, "mv_matrix");
        proj_location = glGetUniformLocation(program, "proj_matrix");

        vao = glGenVertexArrays();
        glBindVertexArray(vao);

        buffer = GL15.glGenBuffers();
        GL15.glBindBuffer(GL_ARRAY_BUFFER, buffer);

        GL15.glBufferData(GL_ARRAY_BUFFER,
                vertex_positions,
                GL_STATIC_DRAW);
        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, NULL);
        glEnableVertexAttribArray(0);

        glEnable(GL_CULL_FACE);
        glFrontFace(GL_CW);

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
    }

    public void run() {
        init();
        loop();

        glfwFreeCallbacks(window);
        glfwDestroyWindow(window);

        // Terminate GLFW and free the error callback
        glfwTerminate();
        glfwSetErrorCallback(null).free();
    }

    private void loop() {

        while (!glfwWindowShouldClose(window)) {
            final float green[] = {0.0f, 0.25f, 0.0f, 1.0f};
            final float one[] = {1.0f};

            IntBuffer w = BufferUtils.createIntBuffer(1);
            IntBuffer h = BufferUtils.createIntBuffer(1);
            glfwGetWindowSize(window, w, h);
            int width = w.get(0);
            int height = h.get(0);
            float aspect = (float) width / (float) height;
            glViewport(0, 0, width, height);
            new Matrix4f()
                    .perspective((float) Math.toRadians(50.0f), aspect, 0.01f, 1000.0f)
                    .lookAt(0.0f, 0.0f, 10.0f,
                            0.0f, 0.0f, 0.0f,
                            0.0f, 1.0f, 0.0f).set(this.proj_matrix);

            double curTime = System.currentTimeMillis() / 1000.0;
            float t = (float) curTime * 0.3f;//assigned direcly but I was applying a factor here

            glClearBufferfv(GL_COLOR, 0, green);
            glClearBufferfv(GL_DEPTH, 0, one);

            glUseProgram(program);
            glUniformMatrix4fv(proj_location, false, proj_matrix);

            FloatBuffer mv_matrix = BufferUtils.createFloatBuffer(16);
            new Matrix4f().translate(new Vector3f(0.0f, 0.0f, -4.0f))
                    .translate(
                            new Vector3f(
                                    (float) Math.sin(2.1 * t) * 0.5f,
                                    (float) Math.cos(1.7 * t) * 0.5f,
                                    (float) Math.sin(1.3 * t)
                                    * (float) Math.cos(1.5 * t) * 2.0f)
                    )
                    .rotate((float) Math.toRadians(45.0f) * t, 0.0f, 1.0f, 0.0f)
                    .rotate((float) Math.toRadians(81.0f) * t, 1.0f, 0.0f, 0.0f)
                    .set(mv_matrix);

            glUniformMatrix4fv(mv_location, false, mv_matrix);
            glDrawArrays(GL_TRIANGLES, 0, 36);

            glfwSwapBuffers(window); // swap the color buffers
            glfwPollEvents();
        }
        glDeleteVertexArrays(vao);
        glDeleteProgram(program);
    }

    private String readFileAsString(String filename) {
        String next = new Scanner(Ch5SpinningCube.class.getResourceAsStream(filename), "UTF-8").useDelimiter("\\A").next();
        System.out.println("readFileAsString: " + next);
        return next;
    }

    private void compileShader() {
        int vertex_shader = createShader("/vert.glsl", GL_VERTEX_SHADER);
        checkShader(vertex_shader);
        int fragment_shader = createShader("/frag.glsl", GL_FRAGMENT_SHADER);
        checkShader(fragment_shader);
        program = glCreateProgram();
        glAttachShader(program, vertex_shader);
        glAttachShader(program, fragment_shader);
        glLinkProgram(program);
        //check link       
        if (glGetProgrami(program, GL_LINK_STATUS) != 1) {
            System.err.println(glGetProgramInfoLog(program));
            System.exit(1);
        }
        glValidateProgram(program);
        if (glGetProgrami(program, GL_VALIDATE_STATUS) != 1) {
            System.err.println(glGetProgramInfoLog(program));
            System.exit(1);
        }
        //delete shaders as the program has them now
        glDeleteShader(vertex_shader);
        glDeleteShader(fragment_shader);
    }

    public int createShader(final String path, final int shaderType) {
        String shaderSource = readFileAsString(path);
        int shader_id = glCreateShader(shaderType);
        glShaderSource(shader_id, shaderSource);
        glCompileShader(shader_id);
        return shader_id;
    }

    public void checkShader(final int shaderId) {
        if (glGetShaderi(shaderId, GL_COMPILE_STATUS) != 1) {
            System.err.println(glGetShaderInfoLog(shaderId));
            System.exit(1);
        }
    }
}

这里供参考的是顶点着色器(vert.glsl):

    #version 410 core                                                 

    in vec4 position;

    out VS_OUT {

        vec4 color;
    } vs_out;

    uniform mat4 mv_matrix;
    uniform mat4 proj_matrix;

    void main(void) 
    {
        gl_Position = proj_matrix * mv_matrix * position;
        vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
    }

和片段着色器(frag.glsl):

#version 410 core                                                

out vec4 color;

in VS_OUT {
    vec4 color;
} fs_in;

void main(void) {
    color = fs_in.color;
}

1 个答案:

答案 0 :(得分:-1)

好的,那么如果你已经成功构建了superbible 7th edition的github句柄的项目,并且运行spinnycube_d.exe给你一个空白的绿屏,然后尝试调整窗口大小,你将能够看到旋转现在的立方体。这样做的原因是 proj_matrix(投影矩阵)的第一个赋值在 onResize() 函数中,并且只有在我们在运行时至少调整了一次窗口大小时才会调用该函数,但在此之前 proj_matrix 是未初始化的,因此它由零组成(作为垃圾值)。 现在如果要解决这个问题,我们需要在startup()函数中初始化这个proj_matrix,所以把这个语句放在startup()函数中: Proj_matrix = vmath::perspective(50.0f, (float) (800/600), 0.1f, 1000.0f) ; 现在重建项目,并运行 sinnycube_d.exe 文件,您现在可以看到立方体(无需调整大小)。