我正在尝试在OpenGL中创建透视窗口效果。 通过背景四边形,我渲染背景纹理。之后,我在顶部渲染透视窗口纹理,并在窗口所在的位置填充模板缓冲区。最后,我只在模板缓冲区有一个网格的地方渲染一个网格。
这是我的OpenGL初始化代码和我的Draw
方法:
// OpenGL state
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Draw method
auto virtual Draw() -> void override
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Update camera UBO
...
// Render background
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
prg_texture2D->UseProgram();
prg_texture2D->SetUniform("modelMatrix", glm::mat4());
glActiveTexture(GL_TEXTURE0);
tex_image->Bind();
backgroundQuad->Render();
tex_image->Unbind();
prg_texture2D->UnUseProgram();
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
// Render window
double x, y;
glfwGetCursorPos(m_window, &x, &y);
glViewport(x - 150, m_windowDimensions.y - y - 150, 300, 300); // see-through window size = 300
glClear(GL_STENCIL_BUFFER_BIT);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glDisable(GL_DEPTH_TEST);
prg_texture2D->UseProgram();
prg_texture2D->SetUniform("modelMatrix", glm::mat4());
glActiveTexture(GL_TEXTURE0);
tex_window->Bind();
backgroundQuad->Render();
tex_window->Unbind();
prg_texture2D->UnUseProgram();
glEnable(GL_DEPTH_TEST);
backgroundQuad->UpdatePositions(vec_positions);
glViewport(0, 0, m_windowDimensions.x, m_windowDimensions.y);
// Update camera UBO
...
// Render skull
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilMask(0x00);
prg_lighting->UseProgram();
skull->ResetModelMatrix();
skull->ScaleModel(glm::vec3(0.005f, 0.005f, 0.005f));
skull->RotateModel(glm::radians(180.0f), glm::vec3(0.0f, 1.0f, 0.0f));
prg_lighting->SetUniform("modelMatrix", skull->GetModelMatrix());
skull->Render(GL_TRIANGLES);
prg_lighting->UnUseProgram();
如果没有调用glViewport
,透明纹理就会在整个屏幕上拉伸,这不是什么,因为窗口应该是可移动的。但是,在这种情况下,模板功能可以正常工作,并且只有在透视窗口后面才能看到网格(我可以旋转,平移等)。
通过调用glViewport
,行为非常奇怪,模板测试通过屏幕的每个部分,自程序启动以来透视窗口已被移动,即如果我移动在整个屏幕上的透视窗口,网格始终可见。
我还尝试更新背景四边形的顶点位置,而不是更改视口,我用它来将纹理渲染到屏幕上。但是,效果完全相同。以下是使用背景四元组更新的代码:
// Render window
double x, y;
glfwGetCursorPos(m_window, &x, &y);
float p = 0.1; // size of see-through window
std::array<glm::vec3, 6> vec_windowPositions = // All in the range of [-1, 1]
{
// First triangle
glm::vec3(2 * (x / m_windowDimensions.x - p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y - p / 2) - 1, 0.0f), // {0}
glm::vec3(2 * (x / m_windowDimensions.x + p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y - p / 2) - 1, 0.0f), // {1}
glm::vec3(2 * (x / m_windowDimensions.x + p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y + p / 2) - 1, 0.0f), // {2}
// Second triangle
glm::vec3(2 * (x / m_windowDimensions.x + p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y + p / 2) - 1, 0.0f), // {2}
glm::vec3(2 * (x / m_windowDimensions.x - p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y + p / 2) - 1, 0.0f), // {3}
glm::vec3(2 * (x / m_windowDimensions.x - p / 2) - 1, 2 * ((m_windowDimensions.y - y) / m_windowDimensions.y - p / 2) - 1, 0.0f) // {0}
};
backgroundQuad->UpdatePositions(vec_windowPositions); // Update new vertex positions
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glDisable(GL_DEPTH_TEST);
prg_texture2D->UseProgram();
prg_texture2D->SetUniform("modelMatrix", glm::mat4());
glActiveTexture(GL_TEXTURE0);
tex_window->Bind();
backgroundQuad->Render();
tex_window->Unbind();
prg_texture2D->UnUseProgram();
glEnable(GL_DEPTH_TEST);
backgroundQuad->UpdatePositions(vec_positions); // Update to old, fulscreen vertex positions
以下是它的外观截图。有任何建议如何解决这个问题?