添加Frame Buffer后gl_FragCoord.y坐标异常的问题求助
问题描述
添加Frame Buffer并向其绘制内容后,默认Frame Buffer的gl_FragCoord.y坐标范围变为底部-600、顶部0,而非原本的底部0、顶部600。尝试调整窗口尺寸、Frame Buffer尺寸及Viewport,但仍无法消除坐标负值问题,只要向Frame Buffer绘制就会触发该异常。测试时通过判断gl_FragCoord.y > -300来提亮颜色,此时屏幕一半区域亮起。
复现代码
#include <glad/glad.h> #include <GLFW/glfw3.h> #include <iostream> // vertex shader const char* vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; // fragment shader const char* fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "vec4 light = vec4(0.1f, 0.1f, 0.1f, 0.1f);\n" "void main()\n" "{\n" "if (gl_FragCoord.y > -300)\n" "{\n" "light = vec4(1.0f, 1.0f, 1.0f, 1.0f);\n" "}\n" "FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f) * light;\n" "}\n\0"; const int Width = 800; const int Height = 600; int main() { glfwInit(); GLFWwindow* window = glfwCreateWindow(Width, Height, "Test", NULL, NULL); glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // vertex shader unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); // fragment shader unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); // link shaders unsigned int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); float square[] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(square), square, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); float vertices[] = { // pos // tex -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f }; unsigned int FBO; unsigned int quadVAO; unsigned int texture; glGenVertexArrays(1, &quadVAO); glGenBuffers(1, &VBO); glBindVertexArray(quadVAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // load framebuffer glGenFramebuffers(1, &FBO); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); // renderbufferobject unsigned int RBO; glGenRenderbuffers(1, &RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, Width, Height); glBindRenderbuffer(GL_RENDERBUFFER, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) { std::cout << "FBO connected" << "\n"; } else { std::cout << "Unable to connect to FBO" << glCheckFramebufferStatus(GL_FRAMEBUFFER) << "\n"; } // render loop while (!glfwWindowShouldClose(window)) { // frame buffer glBindFramebuffer(GL_FRAMEBUFFER, FBO); glClearColor(0.11f, 0.16f, 0.32f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); // draw square glUseProgram(shaderProgram); glBindVertexArray(VAO); // not drawing here stops the issue glDrawArrays(GL_TRIANGLES, 0, 6); // back to default frame buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); glDisable(GL_DEPTH_TEST); glClearColor(0.11f, 0.16f, 0.32f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw square glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 6); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }
问题分析与解决
问题根源是切换回默认帧缓冲后未显式重置视口(Viewport)。绑定FBO并绘制时,OpenGL会自动将视口设置为FBO的尺寸,但FBO的纹理Y轴方向与默认帧缓冲存在差异,切换回默认帧缓冲后,视口原点未被正确重置,导致gl_FragCoord的Y轴范围出现负值。
解决方法:
在切换回默认帧缓冲后,调用glViewport(0, 0, Width, Height)显式设置视口,确保坐标系统与窗口匹配。修改后的渲染循环关键部分如下:
// back to default frame buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); // 显式设置视口,匹配窗口尺寸 glViewport(0, 0, Width, Height); glDisable(GL_DEPTH_TEST); glClearColor(0.11f, 0.16f, 0.32f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw square glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 6);
也可以在初始化时设置一次视口,但由于切换FBO时OpenGL会自动修改视口,建议每次切换帧缓冲后都显式设置对应视口参数,避免坐标偏移问题。
内容的提问来源于stack exchange,提问作者Couchy123
相关产品推荐
相关产品推荐

