【问题标题】:glUseProgram doesn't change shaderglUseProgram 不会改变着色器
【发布时间】:2014-06-04 20:13:20
【问题描述】:

我目前正在开发一个带有(尚未实现)后期效果的应用程序。因此 3D 场景在缓冲区中渲染,然后另一个着色器在屏幕上渲染缓冲区。

我的问题是程序在第二遍中使用我的基本着色器来处理 3d 场景而不是后期效果着色器。你有什么想法,可以这样做吗?

我的方法:我有一个有两个主要功能的类: - bindBuffer() 将渲染目标设置为缓冲区 - renderSSAO() 将缓冲区渲染到屏幕上,并且有朝一日会添加环境光遮蔽效果。 :)

绑定缓冲区功能

void SSAOShader::bindBuffer() {
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
    glViewport(0,0,windowWidth,windowHeight);
}

渲染函数

void SSAOShader::renderSSAO(GLuint currentShader) {
    // set shader
    glUseProgram(shader);

    //draw on Screen
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0,0,windowWidth,windowHeight);

    // clear screen
    glClearColor(0.4, 0.4, 0.4, 1.0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    // bind  texture, pass to shader
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, renderTexture);
    glUniform1i(textureID, 0);

    glBindVertexArray(vertexarray);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);

    glUseProgram(currentShader);
}

渲染循环(函数来自ssaoShader-object)

while (!glfwWindowShouldClose(mainWindow)) {
    ssaoShader->bindBuffer();
    // clear the screen
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    // draw cool stuff

    ssaoShader->renderSSAO(programID);

    // Swap buffers
    glfwSwapBuffers(mainWindow);
    glUseProgram(programID);    
}

所以基本上,渲染目标通过bindBuffer(); 设置到我的缓冲区,然后我用我的基本(phong 等)着色器绘制对象,renderSSAO 函数将目标更改为我的屏幕。此函数还将着色器更改为我的后期效果着色器,并将其更改回之前的状态。 programID 是着色器 GLuint。

我知道问题出在使用的着色器上,因为结果是我在世界原点只有一个带有四边形的黑屏。我也可以像往常一样四处走动。

构造者

SSAOShader::SSAOShader(float windowWidth, float windowHeight, GLuint currentShader) {
    this->windowWidth = windowWidth;
    this->windowHeight = windowHeight;

    //shader
    shader = LoadShaders("Passthrough.vertexshader", "SSAO.fragmentshader");
    glUseProgram(shader);
    textureID = glGetUniformLocation(shader, "renderTexture");
    int status;
    glGetProgramiv(shader, GL_COMPILE_STATUS, &status);
    std::cout << (status == GL_TRUE)    << std::endl;

    GLfloat planeVertices[] = {
        -1, -1,
         1, -1,
        -1,  1,
         1,  1
    };
    // create vertex array
    glGenVertexArrays(1, &vertexarray);
    glBindVertexArray(vertexarray);

    // create "uv" (vertex) buffer
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);

    // add vertecies to as attributes
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2,  GL_FLOAT, GL_FALSE, 0, (void*)0);
    glBindVertexArray(0);



    // ---- set up framebuffer ----
    glGenFramebuffers(1, &framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);

    glGenTextures(1, &renderTexture);
    glBindTexture(GL_TEXTURE_2D, renderTexture);
    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, windowWidth, windowHeight, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    glGenRenderbuffers(1, &depthrenderbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderTexture, 0);
    DrawBuffers[1] = GL_COLOR_ATTACHMENT0;
    glDrawBuffers(1, DrawBuffers);

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
        exit(0); // bad luck
    }
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    //glUseProgram(currentShader);
}

VS2012 项目 https://studi.f4.htw-berlin.de/~s0539750/SSAOTest.zip

对于那些疯狂到看我的代码的人。 ;)

【问题讨论】:

  • 你程序的着色器编译正确并且链接很好?顺便说一句,您应该使用与程序相关的名称而不是着色器来调用着色器程序。这有点令人困惑。一开始我以为你是在着色器上调用glUseProgram
  • 我对 openGL 很陌生,所以我必须习惯这样的东西。 ;) 应用程序告诉我没有编译错误。但是,我只是使用了这个函数,它在GL_TRUE == status 上返回 0:glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;status); 我仍然使用一个为我编译程序的小函数,来自这个页面:opengl-tutorial.org 但是编译时它不会返回任何错误。这可能是什么原因?
  • 如果在glUseProgram(shader)之前和之后调用glGetError(),返回值分别是多少?
  • 等等等等,所以着色器是一个着色器,而不是一个程序。之后你需要将着色器链接到一个程序,然后你使用这个程序与glUseProgram
  • 不,“shader”是一个程序。 (对不起)glGetError 的两个调用都返回 GL_NO_ERROR

标签: opengl shader framebuffer


【解决方案1】:

我发现了问题。

glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderTexture, 0);
DrawBuffers[1] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, DrawBuffers);

构造函数中的这部分改变了我的GLuint shader;。我不知道究竟是为什么,但原因是DrawBuffers 是一个大小为1 的固定数组。显然,访问DrawBuffers[1] 并不是当今最好的主意。 ;)

我的猜测是DarBuffers[1] 用于我的“着色器”GLuint,或者问题是glDrawBuffers 从未真正将GL_COLOR_ATTACHMENT0 附加到我的帧缓冲区。这是什么情况?

顺便感谢大家的帮助,帮了大忙。 :)

【讨论】:

  • 无论如何这都不应该是必要的。 FBO 默认正好有 1 个绘制缓冲区:DrawBuffer0 = GL_COLOR_ATTACHMENT0;其他一切都以GL_NONE 开头。您应该能够安全地从您的答案中删除最后两行代码,并且程序将以您想要的方式运行,假设您从未在代码中的其他任何地方乱用glDrawBuffers (...)
  • 嗨,我已将其更改为使用两个缓冲区。 (纹理和深度纹理)。但感谢您的提示。 :)
  • glDrawBuffer 仅适用于颜色缓冲区,不适用于模板/深度。
  • 似乎我还需要学习很多东西......它以某种方式起作用,以便我可以在第二遍中使用深度纹理。不管我多么愚蠢,我还是没有保存 VS 项目...... ;)
猜你喜欢
  • 2020-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多