OpenGL ES बनावट का उपयोग करके स्टैंसिल प्रभाव बनाते हैं


10

वातावरण

यह वह वातावरण है जिसमें मैं काम कर रहा हूं:

  • ओपन ES 2.0
  • iPhone सिम्युलेटर और iPhone 4
  • iMac 27 "NVIDIA GeForce GTX 680MX 2048 MB का उपयोग कर रहा है

उम्मीद है की वो मदद करदे।

समस्या

Stackoverflow सहित कई स्रोतों और कई साइटों से उच्च और निम्न खोज रहा है, लेकिन एक काम करने वाला स्टैंसिल प्रभाव नहीं मिला है।

मेरे पास यह क्या है:

स्टैंसिल दृश्य सेटअप

काली 'S' चीज बहुभुज नहीं है लेकिन आयताकार क्वाड पर तैयार की गई बनावट है जो पृष्ठभूमि की छवि के समान चौड़ाई और ऊंचाई पर है।

मैं एक स्टैंसिल प्रभाव करने की कोशिश कर रहा हूं, जहां पृष्ठभूमि और छोटे पीले आदमी को केवल तभी दिखाई देना चाहिए जब यह उस काले 'एस' बनावट के भीतर हो।

मेरे टुकड़े टुकड़े में, मेरे पास यह है:

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;
}

मेरे सेटअप डेप्थ स्टैंसिल बफर के लिए, मैंने इसे इस तरह सेट किया है:

-(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);
}

Apple के प्रलेखन के अनुसार (जो मुझे लगता है कि पुराना है):

http://developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_ref/doc/uid/TP40008793-CH103-SW1

ध्यान दें कि GL_RGBA enum जैसी कुछ चीजें मौजूद नहीं हैं जब मैंने इसे Xcode में टाइप करने की कोशिश की (मुझे लगता है कि Apple ने इसे हटा दिया होगा और इसे अप्रचलित कर दिया होगा)।

मैंने ऊपर दिए गए लिंक में तथाकथित "गहराई / स्टैंसिल" बफर को परिभाषित करने के एप्पल के तरीके की भी कोशिश की है, लेकिन इसने नीचे वही त्रुटि दी।

मेरे पास उपरोक्त कोड है कि आप एक स्टैंसिल बफर कैसे बनाएंगे।

मेरे setupFrameBuffer () विधि में, मैं इसे इस तरह संलग्न करता हूं:

-(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);
    }
}

जब मैं इसे संलग्न करता हूं तो त्रुटि मुझे ऊपर दिखाए गए अनुसार है:

पूर्ण फ्रेमबफ़र ऑब्जेक्ट 8cd6 बनाने में विफल

मेरे रेंडर विधि के लिए, मेरे पास यह है:

-(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];
}

इसका परिणाम स्पष्ट रूप से एक गुलाबी स्क्रीन है, जिसका अर्थ है कि मेरा सेटअप गलत है:

यहाँ छवि विवरण दर्ज करें

किसी को कृपया कुछ प्रकाश शेड करने में सक्षम?


पता नहीं कैसे सटीक समस्या को हल करने के लिए, लेकिन क्यों न केवल "स्टैंसिल बनावट" का उपयोग करते समय थोड़ा पीला आदमी ड्राइंग करें, और त्यागें यदि टेक्सल मूल्य मेल नहीं खाता है?
जरी कोमप्पा

स्टैंसिल छोटे आदमी को मास्क करने के लिए नहीं है, यह इलाके का पता लगाने में उपयोग के लिए थोड़े है कि छोटा आदमी खड़ा है (न कि पृष्ठभूमि की छवि जो आप ऊपर देखते हैं)। वर्म गेम के बारे में सोचें, आपको पृष्ठभूमि मिल गई, फिर आपको बीच में इलाका मिला, जो कि एक स्टैंसिल द्वारा नकाब को दोनों इलाकों को मिटा देता है और स्क्रीन (छोटे पीले आदमी) पर खिलाड़ियों के लिए टक्कर का पता लगाने के लिए।
झांग

जवाबों:


7

समाधान

जी हाँ!!!

मैं अब एक खुश चाप हूँ! : डी

ठीक है, मैं अंततः स्टैंसिल को बनावट के साथ काम करने का प्रबंधन करता हूं :)

(रास्ते में कई चीजें भी सीखीं, जैसे हम color.alpha की जांच कर सकते हैं और पारदर्शी पिक्सेल और glBlend (GL_SRC_ALPHA, GL_ONE_MINUS_SINC_ALPHA) ट्रिक अप्रचलित हो जाती है।

तो पहली बात जो मैंने देखी कि मैंने गलत किया था गलत तरीके से मेरे स्टैंसिल बफर के नाम पैदा कर रहा था।

अपने प्रश्न में उपरोक्त स्रोत कोड में, मैंने टाइप किया था:

glGenBuffers(1, &depthStencilBuffer);

यह वास्तव में होना चाहिए:

glGenRenderbuffers(1, &depthStencilBuffer);

डी 'ओह!

सभी में से, मैंने महत्वपूर्ण दूसरी glStbonFunc () टिप्पणी की जिसे कहा जाना चाहिए:

glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

// draw black 'S' textured quad here

. . .

// -----------------------------------
// I WAS MISSING THIS IMPORTANT LINE
// -----------------------------------
glStencilFunc(GL_ALWAYS, 0, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);

/* draw the rest of the scene here (the background and yellow guy) */

अंतिम परिणाम:

यहाँ छवि विवरण दर्ज करें

आशा है कि हर किसी की मदद करता है जो इस शांत स्टैंसिल को एक बनावट विशेषता के साथ कोशिश कर रहा है: डी

मैंने कई अन्य स्रोत कोड भी संशोधित किए लेकिन वे दो मुख्य बदलाव थे जो इसे काम कर रहे थे।

कुछ उपयोगी परिवर्तनों से मुझे समस्या पर बहस करने में मदद मिली:

  • मैंने पाया है कि मुझे अपने फ्रेमबफ़र को काम करने के लिए गहराई बफर संलग्न करने की आवश्यकता नहीं है
  • मुझे GL_DEPTH_BUFFER_BIT साफ़ करने की भी आवश्यकता नहीं है
  • मैंने setupFrameBuffer () पद्धति को अतिरिक्त के साथ बदल दिया है, यदि अतिरिक्त-स्थितियां स्पष्ट रूप से मुझे संभावित त्रुटियों को इंगित करने के लिए।

नया setupFrameBuffer () विधि:

-(void)setupFrameBuffer
{
    GLuint frameBuffer;

    glGenBuffers(1, &frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderBuffer);
    //glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilBuffer);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if(status == GL_FRAMEBUFFER_COMPLETE)
    {
        NSLog(@"framebuffer complete");
        //NSLog(@"failed to make complete framebuffer object %x", status);
    }
    else if(status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
    {
        NSLog(@"incomplete framebuffer attachments");
    }
    else if(status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT)
    {
        NSLog(@"incomplete missing framebuffer attachments");
    }
    else if(status == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS)
    {
        NSLog(@"incomplete framebuffer attachments dimensions");
    }
    else if(status == GL_FRAMEBUFFER_UNSUPPORTED)
    {
        NSLog(@"combination of internal formats used by attachments in thef ramebuffer results in a nonrednerable target");
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.