Umgebung
Dies ist die Umgebung, in der ich arbeite:
- OpenGL ES 2.0
- iPhone Simulator & iPhone 4
- iMac 27 "mit NVIDIA GeForce GTX 680MX 2048 MB
Hoffentlich hilft das.
Das Problem
Ich habe aus mehreren Quellen und mehreren Websites, einschließlich Stackoverflow, hoch und niedrig gesucht, aber keinen funktionierenden Schabloneneffekt erzielt.
Was ich habe ist folgendes:
Das schwarze 'S'-Ding ist kein Polygon, sondern eine Textur, die auf ein Rechteck-Quad gezeichnet wird, das dieselbe Breite und Höhe wie das Hintergrundbild hat.
Ich versuche einen Schabloneneffekt zu erzielen, bei dem der Hintergrund und der kleine gelbe Kerl nur sichtbar sein sollten, wenn er sich innerhalb dieser schwarzen S-Textur befindet.
In meinem Fragment-Shader habe ich Folgendes:
varying lowp vec4 destinationColor;
varying lowp vec2 TexCoordOut;
uniform sampler2D Texture;
uniform highp float TexScale;
void main()
{
highp vec4 color = texture2D(Texture, TexCoordOut);
if(color.a == 0.0)
{
discard;
}
gl_FragColor = color;
}
Für meinen Setup Depth Stencil Buffer habe ich ihn folgendermaßen eingerichtet:
-(void)setupDepthStencilBuffer
{
GLint width;
GLint height;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
glGenBuffers(1, &depthStencilBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height);
//glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_COMPONENT24_OES, width, height);
NSLog(@"depthStencilBuffer = %d", depthStencilBuffer);
}
Laut Apples Dokumentation (die meiner Meinung nach veraltet ist):
Beachten Sie, dass einige Dinge wie die GL_RGBA-Enumeration nicht vorhanden sind, als ich versucht habe, sie in Xcode einzugeben (ich denke, Apple muss sie entfernt und veraltet gemacht haben).
Ich habe auch versucht, wie Apple den sogenannten "Tiefen- / Schablonen" -Puffer im obigen Link definiert, aber es gab den gleichen Fehler unten.
Der Code, den ich oben habe, ist, wie Sie einen Schablonenpuffer erstellen würden.
In meiner setupFrameBuffer () -Methode hänge ich es folgendermaßen an:
-(void)setupFrameBuffer
{
GLuint frameBuffer;
glGenBuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilBuffer);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
NSLog(@"failed to make complete framebuffer object %x", status);
}
}
Der Fehler, den ich beim Anhängen wie oben gezeigt erhalten habe, ist:
Fehler beim Erstellen des vollständigen Framebuffer-Objekts 8cd6
Für meine Rendermethode habe ich Folgendes:
-(void)render:(CADisplayLink *)displayLink
{
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearStencil(0);
glEnable(GL_STENCIL_TEST);
// ----------------------------------------
// Don't write to color or depth buffer
// ----------------------------------------
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// ----------------------------------------
// First set the alpha test so that
// fragments greather than threshold
// will pass thus will set nonzero
// bits masked by 1 in stencil
// ----------------------------------------
glStencilFunc(GL_ALWAYS, 1, 1);
// ----------------------------------------------------------------
// Drawing our stencil
// ----------------------------------------------------------------
glBindBuffer(GL_ARRAY_BUFFER, bgVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bgIBO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, stencilTexture);
glUniform1i(textureUniform, 0);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 3));
glVertexAttribPointer(texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 7));
glDrawElements(GL_TRIANGLE_FAN, sizeof(bgIndices)/sizeof(bgIndices[0]), GL_UNSIGNED_BYTE, 0);
/*
// -----------------------------------------
// Second pass of the fragments less
// or equal than the threshold will pass
// thus will set zero bits masked by 1
// in stencil
// -----------------------------------------
glStencilFunc(GL_ALWAYS, 0, 1);
glBindBuffer(GL_ARRAY_BUFFER, bgVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bgIBO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, stencilTexture);
glUniform1i(textureUniform, 0);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 3));
glVertexAttribPointer(texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 7));
glDrawElements(GL_TRIANGLE_STRIP, sizeof(bgIndices)/sizeof(bgIndices[0]), GL_UNSIGNED_BYTE, 0);
*/
// ---------------------------------------------------
// RE-ENABLING THE COLOR AND DEPTH MASK AGAIN
// TO DRAW REST OF THE SCENE AFTER STENCIL
// ---------------------------------------------------
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glDepthMask(GL_TRUE);
Mat4 frustrumMatrix = [CameraMatrix createOrthographicMatrixUsingLeft:-(self.bounds.size.width / 2.0)
Right:(self.bounds.size.width / 2.0)
Bottom:-(self.bounds.size.height / 2.0)
Top:(self.bounds.size.height / 2.0)
Near:-1.0f
Far:1.0f];
glUniformMatrix4fv(projectionUniform, 1, 0, frustrumMatrix.matrix);
glViewport(0, 0, self.bounds.size.width * self.contentScaleFactor, self.bounds.size.height * self.contentScaleFactor);
// ----------------------------------------------------------------
// Drawing our background first
// ----------------------------------------------------------------
glBindBuffer(GL_ARRAY_BUFFER, bgVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bgIBO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, bgTexture);
glUniform1i(textureUniform, 0);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 3));
glVertexAttribPointer(texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 7));
glDrawElements(GL_TRIANGLE_FAN, sizeof(bgIndices)/sizeof(bgIndices[0]), GL_UNSIGNED_BYTE, 0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, floorTexture);
glUniform1i(textureUniform, 0);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 3));
glVertexAttribPointer(texCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void *)(sizeof(GLfloat) * 7));
glDrawElements(GL_TRIANGLE_FAN, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
[context presentRenderbuffer:GL_RENDERBUFFER];
}
Das Ergebnis ist offensichtlich ein rosa Bildschirm, was bedeutet, dass mein Setup falsch ist:
Kann jemand bitte etwas Licht ins Dunkel bringen?