【问题标题】:Inesplicable OpenGl shader behaviour on macOSXmacOS 上莫名其妙的 OpenGL 着色器行为
【发布时间】:2020-07-21 11:14:04
【问题描述】:

我创建了顶点数组,我创建了着色器,编译并链接它们,但是当我使用 drawarrays 时没有任何反应。

屏幕上没有绘制几何图形,而我应该看到一个红色三角形。
命令行中没有错误完全没有问题,但三角形不会出现。

#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>

using namespace std;

static GLuint compileShader(const string& source,GLuint type);
static int createShader(const string& vertexShader, const string& fragment);

int main(void){

    // I INITIALISE GLFW TO HAVE THE LATEST VERSION OF THE SHADER VERSION
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


    //I CREATE THE WINDOW
    GLFWwindow* window = glfwCreateWindow(800,600,"Dio suino",NULL,NULL);
    glfwMakeContextCurrent(window);
    glewExperimental= GL_TRUE;

    //I INITIALISE GLEW
    if(glewInit()!=GLEW_OK){
        fprintf(stderr,"ERROR");
        exit(1);
    }

    //I SPECIFY THE VERTEX DATA
    float bufferData[6]={
        0.5,-0.5,
        -0.5,-0.5,
        0.0,0.5
    };

    GLuint bufferId;

    // I CREATE THE BUFFER, BIND IT AND SPECIFY ALL THE INFO NEEDED
    glGenBuffers(1,&bufferId);

    glBindBuffer(GL_ARRAY_BUFFER,bufferId);
    glBufferData(GL_ARRAY_BUFFER,6*sizeof(float),bufferData,GL_STATIC_DRAW);
    glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,2*sizeof(float),0);
    glEnableVertexAttribArray(0);


    // I CREATE THE VERTEX AND FRAGMENT SHADERS
    string vs,fs;

    vs = 
    "#version 330 core \n"
    "in vec4 position;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    gl_Position = position;\n"
    "}\n";

    fs =
    "#version 330 core \n"
    "out vec4 color;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    color = vec4(1.0,0.0,0.0,1.0);\n"
    "}\n";

    //I USE THE PROGRAM
    int shaderProgram = createShader(vs,fs);
    glUseProgram(shaderProgram);
    glBindBuffer(GL_ARRAY_BUFFER,0);


    // WINDOW LOOP: CLEAR COLOR, SWAP BUFFER ECC
    while(!glfwWindowShouldClose(window)){


        glClearColor(0,60,80,0);
        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES,0,3); 

        glfwSwapBuffers(window);

        glfwPollEvents();


    }

    cout<< glGetString(GL_VERSION)<<endl;

    return 0;
}

//CREATES THE SHADER PROGRAM WITH ALL THE SHADERS LINKED
static int createShader(const string& vertexShader, const string& fragment)
{
    GLuint program = glCreateProgram();
    GLuint vs = compileShader(vertexShader,GL_VERTEX_SHADER);
    GLuint fs = compileShader(fragment,GL_FRAGMENT_SHADER);

    glAttachShader(program,vs);
    glAttachShader(program,fs);
    glLinkProgram(program);
    glValidateProgram(program);

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;
}

//COMPILES THE SHADER
static GLuint compileShader(const string& source,GLuint type)
{
    GLuint id = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(id,1,&src,nullptr);
    glCompileShader(id);

    int debug;
    glGetShaderiv(id,GL_COMPILE_STATUS,&debug);

    if(debug == GL_FALSE){

        int length;
        glGetShaderiv(id,GL_INFO_LOG_LENGTH,&length);
        char message[length];
        glGetShaderInfoLog(id,length,&length,message);
        fprintf(stderr,"Something went wrong in the shader of type %i: %s",type,message);
        glDeleteShader(id);
    }

    return id;
}

现在这些是我包含的库。
生成文件:

CC = clang++
MAIN = main.cpp
LIB = -lglew -lglfw 
FWORK = -framework OpenGl
NAME = -o dio -std=c++11

all:
    ${CC} ${MAIN} ${LIB} ${FWORK} ${NAME}

我做错了什么?

【问题讨论】:

  • 唯一让我想到的是,当您提供的点值是 2 个浮点数时,您的顶点着色器指定了in vec4 position,即vec2。是否改变它(然后将后面的行更新为gl_Position = vec4(position, 0.0, 1.0) 使其工作?
  • vec4(position,0.0,1.0) 给出编译错误。您的意思是 vec4(position.xy,0.0,1.0) 吗?它编译但仍然没有三角形:'(
  • 不,我的意思是将in vec4 position 更改为in vec2 position 如上所述更改gl_Position = position
  • 没什么。仍然没有三角形,也没有编译错误...
  • 你的VAO呢?它们在核心上下文中不是可选的。

标签: c++ macos opengl glsl glfw


【解决方案1】:

当您使用核心配置文件OpenGL Context 时,您必须创建一个名为Vertex Array Object,因为默认的 VAO (0) 无效。 VAO 说明了顶点数组的规格。

如果您的硬件和驱动程序支持(可能不在 macOSX 上),您可以切换到兼容性配置文件上下文来解决问题:

https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object:

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);

但是,我建议在指定通用顶点数组数据之前创建一个顶点数组对象。在调用glVertexAttribPointerglEnableVertexAttribArray 时,必须绑定VAO,因为这条指令改变了VAO 的状态向量:

GLuint bufferId;
glGenBuffers(1,&bufferId);
glBindBuffer(GL_ARRAY_BUFFER,bufferId);
glBufferData(GL_ARRAY_BUFFER,6*sizeof(float),bufferData,GL_STATIC_DRAW);

GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,2*sizeof(float),0);
glEnableVertexAttribArray(0);

【讨论】:

  • 通过切换到 COMPAT 程序会产生段错误。现在我将尝试添加 vao。 vao是最近的事吗?我关注的教程只有三年的历史,但它没有使用vao,也不需要使用窗口提示来编译着色器。
  • 我不得不切换回核心配置文件,但添加 VAO 后它可以工作了!!!太感谢了!!你能用外行的话解释一下vao到底在做什么吗?这个顶点数组与我之前创建的缓冲区有什么关系?我只是创建并绑定它,但它实际上做了什么来使事情正常工作?
  • @Adonai 我推荐阅读Vertex Array Object。简而言之,VAO 存储了绘制网格所需的所有规范。它不存储顶点数据(数据存储在VBO 中),但它存储对VBO 的引用以及glVertexAttribPointerglEnableVertexAttribArray 指定的所有内容。在兼容性配置文件中有默认的 VAO (0),它在启动时初始化,但在核心中无效。
  • @Adonai 谢谢。不客气。请注意,您的硬件和 OpenGL 驱动程序似乎不支持兼容性配置文件(它对我来说很好)。
猜你喜欢
  • 2012-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 2012-03-12
  • 2019-02-04
相关资源
最近更新 更多