为什么从帧缓冲区创建的纹理没有正确映射
Why the texture created from the framebuffer is not mapping correctly
我正在创建一个大小为 1920 X 1080 的自定义帧缓冲区,然后将此帧缓冲区的纹理映射到大小为 800 X 600 的默认帧缓冲区中的全屏矩形。
我在自定义帧缓冲区的屏幕中央绘制了一个矩形,在映射纹理后我希望矩形出现在中央。
但是矩形出现在左下角。
当我在自定义缓冲区中绘制全屏矩形并将其映射到大小为 800 X 600 的默认帧缓冲区中的全屏矩形而不是全屏显示时,它覆盖了整个左下角。
SCR_WIDTH = 800;
SCR_HEIGHT = 600;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
cont.SetName("RootItem");
TreeModel* model = new TreeModel("RootElement", &cont);
WavefrontRenderer w(model);
w.show();
glfwInit();
int return_code;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Renderer", nullptr, nullptr); // Create the render window
glfwSetWindowPos(window, 1120, 480);
glfwFocusWindow(window);
glfwMakeContextCurrent(window);
GLenum GlewInitResult;
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
glEnable(GL_MULTISAMPLE);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ResourceManager::LoadShader("C:\Shaders\Test\Vert.txt", "C:\Shaders\Test\Frag.txt", nullptr, "ScreenShader");
//create a texture object
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// create a renderbuffer object for depthbuffer
glGenRenderbuffers(1, &rboDepthId);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1920, 1080);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create a framebuffer
glGenFramebuffers(1, &fboMsaaId);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
// attach colorbuffer image to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId , 0);
// attach depthbuffer image to FBO
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window))
{
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
w.render(); // Do rendering here
ResourceManager::GetShader("ScreenShader").Use();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
ResourceManager::GetShader("ScreenShader").Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
renderQuad();
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return a.exec();
}
////////////////////////////////////////// //////////////////////////////////////////////// //// Render Quad函数的定义
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{
if (quadVAO == 0)
{
float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-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
};
// VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glBindVertexArray(0);
}
当您在不同大小的帧缓冲区之间切换时,您必须将视口调整为新大小。使用glViewport
to set the viewport. The size of the default framebuffer can be get by glfwGetFramebufferSize
(当window的大小改变时window帧缓冲区的大小改变)。
此外,OpenGL 是一个状态引擎。状态是持久的,直到它们再次改变,甚至超出框架。如果第一遍使用 Depth Test,但第二遍不使用,则必须在循环中打开和关闭深度测试:
int main(int argc, char *argv[])
{
// [...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, ....);
// [...]
while (!glfwWindowShouldClose(window))
{
int sizex, sizey;
glfwGetFramebufferSize(window, &sizex, &sizey);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glViewport(0, 0, 1920, 1080);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_DEPTH_TEST);
// [...]
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, sizex, sizey);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// [...]
}
}
我正在创建一个大小为 1920 X 1080 的自定义帧缓冲区,然后将此帧缓冲区的纹理映射到大小为 800 X 600 的默认帧缓冲区中的全屏矩形。
我在自定义帧缓冲区的屏幕中央绘制了一个矩形,在映射纹理后我希望矩形出现在中央。
但是矩形出现在左下角。
当我在自定义缓冲区中绘制全屏矩形并将其映射到大小为 800 X 600 的默认帧缓冲区中的全屏矩形而不是全屏显示时,它覆盖了整个左下角。
SCR_WIDTH = 800;
SCR_HEIGHT = 600;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
cont.SetName("RootItem");
TreeModel* model = new TreeModel("RootElement", &cont);
WavefrontRenderer w(model);
w.show();
glfwInit();
int return_code;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Renderer", nullptr, nullptr); // Create the render window
glfwSetWindowPos(window, 1120, 480);
glfwFocusWindow(window);
glfwMakeContextCurrent(window);
GLenum GlewInitResult;
glewExperimental = GL_TRUE;
GlewInitResult = glewInit();
glEnable(GL_MULTISAMPLE);
glEnable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ResourceManager::LoadShader("C:\Shaders\Test\Vert.txt", "C:\Shaders\Test\Frag.txt", nullptr, "ScreenShader");
//create a texture object
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
// create a renderbuffer object for depthbuffer
glGenRenderbuffers(1, &rboDepthId);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthId);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 1920, 1080);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
// create a framebuffer
glGenFramebuffers(1, &fboMsaaId);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
// attach colorbuffer image to FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId , 0);
// attach depthbuffer image to FBO
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthId);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
while (!glfwWindowShouldClose(window))
{
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
w.render(); // Do rendering here
ResourceManager::GetShader("ScreenShader").Use();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
ResourceManager::GetShader("ScreenShader").Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
renderQuad();
glfwPollEvents();
glfwSwapBuffers(window);
}
glfwTerminate();
return a.exec();
}
////////////////////////////////////////// //////////////////////////////////////////////// //// Render Quad函数的定义
unsigned int quadVAO = 0;
unsigned int quadVBO;
void renderQuad()
{
if (quadVAO == 0)
{
float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-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
};
// VAO
glGenVertexArrays(1, &quadVAO);
glGenBuffers(1, &quadVBO);
glBindVertexArray(quadVAO);
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
}
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
glBindVertexArray(0);
}
当您在不同大小的帧缓冲区之间切换时,您必须将视口调整为新大小。使用glViewport
to set the viewport. The size of the default framebuffer can be get by glfwGetFramebufferSize
(当window的大小改变时window帧缓冲区的大小改变)。
此外,OpenGL 是一个状态引擎。状态是持久的,直到它们再次改变,甚至超出框架。如果第一遍使用 Depth Test,但第二遍不使用,则必须在循环中打开和关闭深度测试:
int main(int argc, char *argv[])
{
// [...]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1920, 1080, ....);
// [...]
while (!glfwWindowShouldClose(window))
{
int sizex, sizey;
glfwGetFramebufferSize(window, &sizex, &sizey);
glBindFramebuffer(GL_FRAMEBUFFER, fboMsaaId);
glViewport(0, 0, 1920, 1080);
glClearColor(1.0, 0.0, 0.0, 1.0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glEnable(GL_DEPTH_TEST);
// [...]
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, sizex, sizey);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
// [...]
}
}