我正在开发下面描述的程序。 我画了两个不同深度的三角形。 对于下面的例子,我想将绿色三角形分成可见部分和隐藏部分。然后,最后使用混合功能,绿色三角形的隐藏部分被着色为透明,可见部分被着色为原始颜色。
现在,我使用opengl-ES(使用JNI)编写代码。 而且,我有两个问题。
第一:
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glUseProgram(gProgram);
glGetUniformLocation(gProgram, "vColor");
const GLfloat gTriangleVertices1[] =
{
-0.5f, -0.5f, -0.5f,
0.0f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
};
float color1[] = {1.0f, 0.0f, 0.0f};
const GLfloat gTriangleVertices2[] =
{
-0.7f, 0.0f, 0.3f,
0.5f, 0.3f, 0.3f,
0.5f, 0.0f, 0.3f,
};
float color2[] = {0.0f, 1.0f, 0.0f};
int mColorHandle1;
int mColorHandle2;
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glClearDepthf(1.0f);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]);
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1);
glEnableVertexAttribArray(gvPositionHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDepthFunc(GL_GREATER);
//glDepthFunc(GL_LESS);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], color2[3]);
glDrawArrays(GL_TRIANGLES, 3, 3);
glDisableVertexAttribArray(gvPositionHandle);
从此代码中,如果我将glDepthFunc(GL_GREATER)更改为glDepthFunc(GL_LESS),结果将正确显示可见和隐藏部分。 但是,我不明白为什么它显示正确的答案。 因为,我添加了顶点gTriangleVertices1,但我没有添加gTriangleVertices2。 即使你不添加三角形2的顶点,它也给了我正确答案。为什么吗
第二个问题,我认为使用混合功能是正确的(我检查过它适用于glut / freeglut)。但为什么它不适用于gl-es。
///////////////////////// visible part /////////////////////////
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glClearDepthf(1.0f);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]);
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1);
glEnableVertexAttribArray(gvPositionHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDepthFunc(GL_LESS);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], color2[3]);
glDrawArrays(GL_TRIANGLES, 3, 3);
glDisableVertexAttribArray(gvPositionHandle);
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS); // same to initialize depth func
///////////////////////// visible part /////////////////////////
///////////////////////// hidden part /////////////////////////
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glClearDepthf(1.0f);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glUniform4f(mColorHandle1, color1[0], color1[1], color1[2], color1[3]);
glVertexAttribPointer(gvPositionHandle, 3, GL_FLOAT, GL_FALSE, 0, gTriangleVertices1);
glEnableVertexAttribArray(gvPositionHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDepthFunc(GL_GREATER);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glUniform4f(mColorHandle2, color2[0], color2[1], color2[2], 0.5f);
glDrawArrays(GL_TRIANGLES, 3, 3);
glDisableVertexAttribArray(gvPositionHandle);
///////////////////////// hidden part /////////////////////////
我刚添加了混合功能。如果我单独使用可见/隐藏部分,它会给出正确的结果。但是如果我使用混合功能,它会产生如下所示的奇怪结果:它给出了透明隐藏的绿色三角形。 怎么了?
答案 0 :(得分:0)
第一个问题:
您通过说glDrawArrays(GL_TRIANGLES, 3, 3);
创建了一个主要错误,因为这会在缓冲区上产生溢出。它的结果是意外的,但在你的情况下,你的编译器似乎已经决定你定义的两个数组紧密包装:
const GLfloat gTriangleVertices1[] =
{
-0.5f, -0.5f, -0.5f,
0.0f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
};
const GLfloat gTriangleVertices2[] =
{
-0.7f, 0.0f, 0.3f,
0.5f, 0.3f, 0.3f,
0.5f, 0.0f, 0.3f,
};
并被视为
const GLfloat gTriangleVertices[] =
{
-0.5f, -0.5f, -0.5f,
0.0f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.7f, 0.0f, 0.3f,
0.5f, 0.3f, 0.3f,
0.5f, 0.0f, 0.3f,
};
因此溢出实际上会跳转到第二个顶点数据所在的内存部分。毫无疑问,错误地认为你所做的是正确的。这是不正确的,这可以打破不同的版本或任何其他原因,平台,设备...所以解决它。
第二个问题:
混合和深度缓冲区不能一起使用。你需要避免这种组合。我不会在这里解释原因(稍微搜索一下),但结果是未定义的,你可能不会使用它。使用其中一个。
如果您将在网上搜索如何解决这个问题,那么您将无法找到适合您情况的正确答案,因为它非常独特。我建议你的一般解决方案是添加一个模板缓冲区。
第一个调用也应该绘制到模板缓冲区,然后用于在最后一个调用中绘制。因此,最后一次调用应禁用深度测试,但启用模板。但这样做你最有可能只是删除深度并仅使用模板。
我确信通过使用alpha通道还有其他可能的解决方案,但在任何情况下都要记住深度缓冲区与混合相结合是严格禁止的,行为是未定义的。这意味着它甚至可以在GPU之间变化。