在opengl场景背景中画出纹理四边形

时间:2013-09-18 09:42:04

标签: ios opengl-es opengl-es-2.0 opengl-es-1.1

代码流程如下:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderScene();
renderTexturedQuadForBackground();
presentRenderbuffer();

有没有什么方法可以让我在场景后面显示纹理四边形渲染代码,尽管场景首先呈现?假设我无法改变背景纹理四边形的渲染将在我呈现渲染缓冲区之前直接发生。

重新说明:我无法更改渲染顺序。基本上我想要的是每个像素只能被glClearColor着色而是被这个纹理四边形着色。

2 个答案:

答案 0 :(得分:4)

最简单的解决方案是直接在规范化设备坐标中定义四边形,并将z值设置为1.然后,您不需要投影四边形,它将是屏幕填充< em>和在其他任何东西后面 - 除了在投影和透视分割之后也在z = 1的东西。

这几乎是屏幕对齐四边形的标准程序,除了通常不需要将四边形置于z = 1,而不是它很重要。通常,全屏幕四边形仅用于处理每个像素至少一次片段,通常是片段和像素的1:1映射。延迟阴影,后处理fx或图像处理通常是常见的嫌疑。由于你只在大多数情况下渲染四边形(而没有别的),深度值是无关紧要的,只要它在单位立方体内并且不被深度测试丢弃,例如当你把它放在z = 1并且你的深度函数时是LESS

编辑:我犯了一个小错误。 NDC在左手坐标系中定义,意味着近平面映射到-1,远平面映射到1.因此,您需要在ND值为1的NDC中定义四边形并设置{{ 1}}到DepthFunc。或者,您可以保持深度函数不变,只需从1.f:

中减去一个非常小的值

LEQUAL

EDIT2 :让我们假设您要渲染一个屏幕对齐的四边形,它在其他所有内容后面并使用适当的纹理坐标绘制。 请注意:我在这里的桌面上,所以我正在编写核心GL代码,而不是直接映射到GLES 2.0。但是,我的考试中没有任何内容与GLES和GLSL ES 2.0无关。

您可以像这样定义四边形的顶点属性(不会弄乱深度函数):

float maxZ = 1.f - std::numeric_limits<float>::epsilon();

相应地设置VAO和缓冲区:

GLfloat maxZ = 1.f - std::numeric_limits<GLfloat>::epsilon ();

// interleaved positions an tex coords
GLfloat quad[] = {-1.f, -1.f, maxZ, 1.f, // v0
                   0.f,  0.f, 0.f,  0.f, // t0
                   1.f, -1.f, maxZ, 1.f, // ...
                   1.f,  0.f, 0.f,  0.f,
                   1.f,  1.f, maxZ, 1.f,
                   1.f,  1.f, 0.f,  0.f,
                  -1.f,  1.f, maxZ, 1.f,
                   0.f,  1.f, 0.f,  0.f};

GLubyte indices[] = {0, 1, 2, 0, 2, 3};

着色器代码来自一个非常非常简单的传递顶点着色器,并且为了简单起见,片段着色器在我的示例中只是导出插值的tex坐标:

// generate and bind a VAO
gl::GenVertexArrays (1, &vao);
gl::BindVertexArray (vao);

// setup our VBO
gl::GenBuffers (1, &vbo);
gl::BindBuffer (gl::ARRAY_BUFFER, vbo);
gl::BufferData (gl::ARRAY_BUFFER, sizeof(quad), quad, gl::STATIC_DRAW);

// setup out index buffer
gl::GenBuffers (1, &ibo);
gl::BindBuffer (gl::ELEMENT_ARRAY_BUFFER, ibo);
gl::BufferData (gl::ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, gl::STATIC_DRAW);

// setup our vertex arrays
gl::VertexAttribPointer (0, 4, gl::FLOAT, gl::FALSE_, 8 * sizeof(GLfloat), 0);
gl::VertexAttribPointer (1, 4, gl::FLOAT, gl::FALSE_, 8 * sizeof(GLfloat), (GLvoid*)(4 * sizeof(GLfloat)));
gl::EnableVertexAttribArray (0);
gl::EnableVertexAttribArray (1);

如您所见,写入// Vertex Shader #version 430 core layout (location = 0) in vec4 Position; layout (location = 1) in vec4 TexCoord; out vec2 vTexCoord; void main() { vTexCoord = TexCoord.xy; // you don't need to project, you're already in NDCs! gl_Position = Position; } //Fragment Shader #version 430 core in vec2 vTexCoord; out vec4 FragColor; void main() { FragColor = vec4(vTexCoord, 0.0, 1.0); } 的值只是传递给着色器调用的顶点位置。没有投影,因为投影和透视分割的结果只不过是标准化的设备坐标。由于我们已经在国家数据中心,我们不需要投影和视角分割,因此只需通过不变的位置。

最终深度非常接近深度范围的最大值,因此四边形似乎落后于场景中的其他深度。

您可以照常使用texcoords。

我希望你明白这个主意。除了GLES 2.0不支持的显式attrib位置(即用BindAttribLocation()调用代替),你不应该做任何事情。

答案 1 :(得分:0)

有一种方法,但你必须把四边形放在场景后面。如果您的四边形构造正确,您可以 使用

启用DEPTH_TEST
glEnable(DEPTH_TEST);

然后使用

glDepthFunc(GL_GREATER);
在渲染背景之前

。 您的四边形将在场景后面渲染。但正如我所说,这只有在您的几何体确实位于场景后面时才有效。