【问题标题】:First triangle does not render after using GLSL-shaders使用 GLSL 着色器后第一个三角形不渲染
【发布时间】:2013-12-07 20:44:58
【问题描述】:

我目前正在通过tutorial 学习 OpenGL(和 GLSL)。到目前为止,我完成了教程 2:第一个三角形。我的代码有点不同,因为我更喜欢编写 C,而不是更常见的 C++。另外,我使用 glfw3 打开了我的窗口,我相信教程使用 glfw。就目前而言,我已经能够用 C 编写所有内容,并且一切正常,直到我使用了我的第一个着色器。每当我使用它们时,我的三角形都不会渲染。我在 Mac 上,没有时间升级到 OSX 10.9 (Mavericks),因此我不得不使用 OpenGL 3.2 和 GLSL 1.2。

tl;dr: 问题:每当我使用着色器时,我的三角形都不会渲染。

这是我的代码:

int main(void) {
GLFWwindow* window;

/* Initialize the library */
if(!glfwInit()) {
    return -1;
}

/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Tutorial 1", NULL, NULL);
if (!window) {
    glfwTerminate();
    return -1;
}

/* Make the window's context current */
glfwMakeContextCurrent(window);

/* Initialize GLEW */
glewExperimental = GL_TRUE; // Needed in core profile
if(glewInit() != GLEW_OK) {
    fprintf(stderr, "Failed to initialize GLEW\n");
    return -1;
}

GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);

/* Triangle's vertices */
static const GLfloat g_vertex_buffer_data[] = {
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,
    0.0f,  1.0f, 0.0f,
};

// This will identify our vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer, put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The following commands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
// Give our vertices to OpenGL.
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);  

// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders("VertexShader.txt", "FragmentShader.txt");

glClearColor(0.0f, 0.0f, 0.4f, 0.0f);

/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window)) {
    /* Render here */
    // 1rst attribute buffer : vertices
    glClear(GL_COLOR_BUFFER_BIT);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );

    // Use our shader
    glUseProgram(programID);

    // Draw the triangle !
    glDrawArrays(GL_TRIANGLES, 0, 3); // Starting from vertex 0; 3 vertices total -> 1 triangle
    glDisableVertexAttribArray(0);

    /* Swap front and back buffers */
    glfwSwapBuffers(window);
    /* Poll for and process events */
    glfwPollEvents();
}

glfwTerminate();
return 0;
}

这是我的顶点着色器:

#version 120
vec3 vertexPosition_modelspace;

void main() {
    gl_Position.xyz = vertexPosition_modelspace;
    gl_Position.w = 1.0;
}

我的 FragmentShader:

#version 120
vec3 color;

void main() {
    color = vec3(1, 0, 0);
}

我认为这可能与着色器文件有关,我想我可能在教程中将它们翻译错了(他使用 GLSL 3.3)。

【问题讨论】:

  • @AntonD:实际上,因为他使用的是 1.20 版本,所以应该是 attribute。此外,片段着色器的输出未正确声明。
  • @derhass 那么我的片段着色器的输出实际上有什么问题,我知道我不能使用 vec3 颜色,因为根据我去过的一些网站,这是一个更高版本.
  • Andon M. Coleman 的回答解释了所有必要的内容

标签: opengl glsl


【解决方案1】:

您的着色器有两个主要问题,问题的症结归结为您如何声明用于着色器输入和输出的变量。

在您的顶点着色器中,您有一个输入:vec3 vertexPosition_modelspace

  • 使用 GLSL 1.20 语法,这应该是 attribute vec3 vertexPosition_modelspace

在您的片段着色器中,您有一个输出:vec3 color (在 GLSL 3.30 教程中为 out vec3 color

  • 您不能在 GLSL 1.20 中将任意变量声明为片段着色器输出,您必须使用 gl_FragColor 或者如果您想输出到特定的绘图缓冲区:gl_FragData [n]

        旁注:切勿将两者混用。


更正的顶点着色器:

 #version 120
 attribute vec3 vertexPosition_modelspace;

 //in vec3 vertexPosition_modelspace;
 //^^ It was probably written this way in the GLSL 3.30 tutorial

 void main() {
   gl_Position.xyz = vertexPosition_modelspace;
   gl_Position.w = 1.0;
 }

更正片段着色器:

 #version 120
 //out vec3 color; -- DO NOT DO THIS IN GLSL 1.20

 void main() {
   //color = vec3(1, 0, 0);
   gl_FragColor = vec4 (1.0, 0.0, 0.0, 0.0);
 }

最后一点,您必须将属性绑定位置与属性指针位置相匹配。由于 GLSL 1.20 不支持 layout 限定符,因此最好的方法是在程序中添加额外的代码行:

glBindAttribLocation (programID, 0, "vertexPosition_modelspace");

【讨论】:

  • 好吧,我更新了我的着色器,并在我链接我的程序的部分和我附加着色器的部分之间放置了附加函数(如果我理解参考正确的话)但它仍然不会显示我是红色三角形。我做的事情对吗?还是我需要 glGetAttribLocation() 来检索我的索引?
  • @Meastroman:等等,你是说在附加着色器之前链接你的程序吗?你应该编译你的着色器,附加它们,绑定属性位置,然后链接。我建议您在使用时查看glGetShaderInfoLog (...)glGetProgramInfoLog (...) - GLSL 编译器和链接器将像任何普通编译器一样生成有用的错误和警告日志。
  • 不抱歉,这不是我的意思,我在链接之前先附上它们。但我突然收到一条警告:“找不到顶点着色器属性 'vertexPosition_modelspace' 来匹配 BindAttributeLocation 请求。”所以现在我正在尝试解决这个问题:P 我希望一旦我弄清楚这一点,我会看到我的红色三角形。
  • 最后我设法解决了我的问题,我的两个着色器都有两个版本,当我完成编辑时,我忘记了使用 vertexShader2.txt 和 fragmentShader2.txt。但是感谢您对 GLSL 的帮助和解释
猜你喜欢
  • 2016-09-12
  • 2018-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多