【问题标题】:Does LWJGL3 and OpenGL need a shader to render?LWJGL3 和 OpenGL 是否需要着色器才能渲染?
【发布时间】:2020-03-25 19:40:26
【问题描述】:

我的代码不起作用。我认为有一种方法可以在没有着色器的情况下在屏幕上渲染某些东西,但是如何?我听说了一些关于现代 OpenGL 渲染以及 OpenGL 如何需要着色器来渲染的信息。帮帮我。

这是我的代码:

import static org.lwjgl.glfw.GLFW.glfwDestroyWindow;
import static org.lwjgl.glfw.GLFW.glfwTerminate;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL30;
import org.lwjgl.system.MemoryUtil;

public class Main {

     public static long window;
     public static boolean running = true;

     public static void createWindow() { 
        GLFW.glfwInit();

        GLFW.glfwDefaultWindowHints();
        GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_FALSE);
        GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GL30.GL_TRUE);

        window = GLFW.glfwCreateWindow(600, 600, "RenderQuad", 0, 0);

        GLFW.glfwMakeContextCurrent(window);

        GLFWVidMode vidmode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());

        GLFW.glfwSetWindowPos(window, (vidmode.width() - 600) / 2, (vidmode.height() - 600) / 2);

        GLFW.glfwShowWindow(window);

        GL.createCapabilities();

        GL30.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    }

    public static int vaoID;
    public static int vboID;

    public static void render() {
        float[] vertices = {
                -0.5f, 0.5f, 0f,
                -0.5f, -0.5f, 0f,
                0.5f, -0.5f, 0f,
                0.5f, -0.5f, 0f,
                0.5f, 0.5f, 0f,
                -0.5f, 0.5f, 0f
        };

        vaoID = GL30.glGenVertexArrays();
        GL30.glBindVertexArray(vaoID);

        FloatBuffer buffer = MemoryUtil.memAllocFloat(vertices.length);
        buffer.put(vertices);
        buffer.flip();

        vboID = GL30.glGenBuffers();
        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, vboID);
        GL30.glBufferData(GL30.GL_ARRAY_BUFFER, buffer, GL30.GL_STATIC_DRAW);
        MemoryUtil.memFree(buffer);

        GL30.glVertexAttribPointer(0, 3, GL30.GL_FLOAT, false, 0, 0);

        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);

        GL30.glBindVertexArray(0);
    }

    public static void loopCycle() {
        GL30.glClear(GL30.GL_COLOR_BUFFER_BIT);

        GL30.glEnableVertexAttribArray(0);

        GL30.glBindVertexArray(vaoID);
        GL30.glDrawArrays(GL30.GL_TRIANGLES, 0, 6);

        GL30.glDisableVertexAttribArray(0);
        GL30.glBindVertexArray(0);
    }

    public static void clean() {
        GL30.glDisableVertexAttribArray(0);

        GL30.glBindBuffer(GL30.GL_ARRAY_BUFFER, 0);
        GL30.glBindVertexArray(0);

        GL30.glDeleteBuffers(vboID);
        GL30.glDeleteVertexArrays(vaoID);


        glfwDestroyWindow(window);
        glfwTerminate();
    }

    public static void loop() {
        GLFW.glfwSwapBuffers(window);
        GLFW.glfwPollEvents();
        //GL30.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
    }

    public static void main(String[] args) {
        createWindow();
        render();

        while(running) {
            if(GLFW.glfwWindowShouldClose(window)) {running = false; break;}
            loopCycle();
            loop();
        }   
        clean();
    }
}

【问题讨论】:

  • 是的,OpenGL 需要着色器来渲染。一些驱动程序可能在没有着色器的情况下实现了默认行为,但这并不能得到规范的保证,并且很可能不会满足您的需求。请遵循任何现代 OpenGL 教程。
  • @ybungalobill 实际上,GLFW 将请求带有默认窗口提示的旧版上下文,因此仍然支持不使用着色器进行绘制,只是不应该期望获得 modern GL 上下文用那个。
  • 你的问题是你从来没有启用在draw call中有效的顶点数组对象中的顶点数组属性。您在默认 VAO 上启用顶点数组属性,然后绑定未启用该属性的 VAO,然后在您的 VAO 上禁用已禁用的属性。
  • ...GL30.glEnableVertexAttribArray(0); 必须在GL30.glBindVertexArray(vaoID); 之后完成。

标签: opengl shader lwjgl


【解决方案1】:

绘制时没有启用顶点属性 0 的数组。每个顶点属性的数组启用状态是VAO的一部分,当你调用glEnableVertexAttribArray时会影响当前绑定的VAO

我不知道这是从哪里来的,但是很多人(而且似乎还有教程)使用这样的方案:

Setup() {
  glGenVertexArrays(1, &vao);
  glBindVertexArray(vao);
  // ... [set up some VBOs and maybe EBO]
  glVertexAttribPointer(...);
  glBindVertexArray(vao);
}

Draw()
{
  glBindVertexArray(vao);
  glEnableVertexAttribArray(...); 
  glDraw...(...);
  glDisableVertexAttribArray(...); 
  glBindVertexArray(0);
}

现在这个方案原则上是可行的,你只是在 VAO 0 仍然绑定时错误地启用了数组,然后切换到 vao根本没有启用任何数组

但是这个方案完全没有效率,VAO 确实存储这些信息是有原因的:这样你就不必在每次想要使用它时重新指定它。因此,glEnableVertexAttribArray() 属于 Setup 函数,并且只有在该特定 VAO 的实际顶点属性集发生更改时才应再次调用(在这些示例中从不)。

我听说了一些关于现代 OpenGL 渲染以及 OpenGL 如何需要着色器来渲染的信息。

是的。请注意,着色器是在 2004 年以 2.0 版引入 OpenGL 的,因此对于 GPU 开发而言,这与 现代 一词相当相似。您真的应该考虑切换到 3.2 core profile 上下文,其中所有 90 年代遗留下来的已弃用的旧内容都将被删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 2012-02-27
    • 2013-10-05
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 2018-02-17
    相关资源
    最近更新 更多