OpenGL ES tạo hiệu ứng stprint bằng cách sử dụng kết cấu


10

Môi trường

Đây là môi trường tôi đang làm việc:

  • OpenGL ES 2.0
  • Mô phỏng iPhone & iPhone 4
  • iMac 27 "sử dụng NVIDIA GeForce GTX 680MX 2048 MB

Mong rằng sẽ giúp.

Vấn đề

Đã tìm kiếm cao và thấp từ nhiều nguồn và nhiều trang web, bao gồm cả Stackoverflow nhưng vẫn chưa có hiệu ứng stprint hoạt động.

Những gì tôi có là đây:

thiết lập cảnh stpson

Thứ 'S' màu đen không phải là một đa giác mà là một kết cấu được vẽ trên một hình chữ nhật có cùng chiều rộng và chiều cao với hình nền.

Tôi đang cố gắng thực hiện một hiệu ứng tô màu trong đó nền và anh chàng nhỏ màu vàng chỉ nên nhìn thấy nếu nó nằm trong kết cấu 'S' màu đen đó.

Trong shader mảnh của tôi, tôi có điều này:

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

Đối với thiết lập của tôi Bộ đệm sâu Depth, tôi đã thiết lập nó như thế này:

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

Theo tài liệu của Apple (mà tôi nghĩ đã lỗi thời):

http://developer.apple.com/lvern/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/WorkingwithEAGLContexts/WorkingwithEAGLContexts.html#//apple_Vf/doc/uid

Lưu ý một số điều như GL_RGBA enum không tồn tại khi tôi cố gắng nhập nó vào Xcode (Tôi nghĩ rằng Apple phải xóa nó và làm cho nó trở nên lỗi thời).

Tôi cũng đã thử cách của Apple để xác định bộ đệm được gọi là "độ sâu / stprint" trong liên kết ở trên nhưng nó đã đưa ra lỗi tương tự bên dưới.

Mã tôi có ở trên là cách bạn sẽ tạo một bộ đệm stpson.

Trong phương thức setupFrameBuffer () của tôi, tôi đính kèm nó như vậy:

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

Lỗi tôi gặp phải khi đính kèm nó như hiển thị ở trên là:

không thể tạo đối tượng bộ đệm hoàn chỉnh 8cd6

Đối với phương thức kết xuất của tôi, tôi có điều này:

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

Kết quả của việc này rõ ràng là một màn hình màu hồng có nghĩa là thiết lập của tôi sai:

nhập mô tả hình ảnh ở đây

Bất cứ ai có thể làm sáng tỏ một số xin vui lòng?


Không biết làm thế nào để giải quyết vấn đề chính xác, nhưng tại sao không sử dụng "kết cấu stprint" trong khi vẽ anh chàng nhỏ màu vàng và loại bỏ nếu giá trị texel không khớp?
Jari Komppa

Tấm gương không phải để che giấu anh chàng nhỏ bé, nó được sử dụng để phát hiện địa hình mà anh chàng nhỏ bé đứng (không phải hình nền bạn nhìn thấy ở trên). Hãy nghĩ về trò chơi Worm, bạn có nền tảng, sau đó bạn có địa hình ở giữa, được che bởi một tấm giấy để vừa xóa địa hình vừa phát hiện va chạm cho người chơi trên màn hình (anh chàng nhỏ màu vàng).
Zhang

Câu trả lời:


7

Giải pháp

Chúa ơi

Bây giờ tôi là một chap hạnh phúc! : D

OK, cuối cùng tôi cũng có thể làm cho Macintosh hoạt động với kết cấu :)

.

Vì vậy, điều đầu tiên tôi nhận thấy tôi đã làm sai là tạo sai tên cho bộ đệm stpson của tôi.

Trong mã nguồn trên trong câu hỏi của tôi, tôi đã gõ:

glGenBuffers(1, &depthStencilBuffer);

Điều này thực sự nên:

glGenRenderbuffers(1, &depthStencilBuffer);

ôi!

Thứ hai, tôi đã nhận xét glStpsonFunc () thứ hai quan trọng cần được gọi là:

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) */

Kết quả cuối cùng:

nhập mô tả hình ảnh ở đây

Hy vọng rằng sẽ giúp tất cả những người khác đang thử bản vẽ tuyệt vời này với tính năng kết cấu: D

Tôi cũng đã sửa đổi một số mã nguồn khác nhưng hai cái đó là những thay đổi chính khiến nó hoạt động.

Một số thay đổi hữu ích cũng giúp tôi gỡ lỗi vấn đề:

  • Tôi đã thấy rằng tôi không cần phải gắn bộ đệm sâu vào bộ đệm khung của mình để làm cho nó hoạt động
  • Tôi cũng không cần xóa GL_DEPTH_BUFFER_BIT
  • Tôi đã thay đổi phương thức setupFrameBuffer () thành điều kiện này với các điều kiện if-other bổ sung để chỉ rõ cho tôi các lỗi có thể xảy ra.

Phương thức setupFrameBuffer () mới:

-(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");
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.