iOS:如何在 GLES2 中渲染至 1 通道纹理

发布于 2024-11-08 18:07:11 字数 4374 浏览 5 评论 0原文

经过几个小时的抨击后,我现在非常确定这是不可能完成的。

这是我迄今为止用于渲染纹理的代码(如下);它可以完成工作,但非常浪费。我只想要一个 8 位通道,可能是 16 位灰度。我不想要无用的RG和B通道。

但是如果我尝试在 glTexImage2D 中切换 GL_RGBA /*GL_ALPHA*/ ,glCheckFramebufferStatus 会捕获“帧缓冲区不完整”错误: 36054 0x8CD6 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

IRC 上的人建议 GL_R 但 Xcode 不提供自动完成功能,所以看起来可能是这样从 GL 中删除的内容之一对于 GLES

但这看起来真的很奇怪!这是一个移动设备。当然,某些东西可以将执行操作所需的位数减少四倍……当然,这将是最后要删除的东西之一。

?!?

有人能明确地埋葬这个吗?是否可以在GLES2.0中渲染到单通道纹理上?

+ (void)  blurTexture: (GLuint)     in_texId
             POTWidth: (GLuint)     in_W
            POTHeight: (GLuint)     in_H
       returningTexId: (GLuint*)    out_pTexId
{
    // search HELP: 'Using a Framebuffer Object as a Texture'
    // http://stackoverflow.com/questions/3613889/gl-framebuffer-incomplete-attachment-when-trying-to-attach-texture

    // Create the destination texture, and attach it to the framebuffer’s color attachment point.

    // create the texture
    GLuint id_texDest;
    {
        // fragshader will use 0 
        glActiveTexture( GL_TEXTURE0 );

        // Ask GL to give us a texture-ID for us to use
        glGenTextures( 1, & id_texDest );
        glBindTexture( GL_TEXTURE_2D, id_texDest );


        // actually allocate memory for this texture
        GLuint pixCount = in_W * in_H;

        typedef struct { uint8_t r, g, b, a } rgba;

        rgba * alphas = calloc( pixCount, sizeof( rgba ) );

        // XOR texture
        int pix=0;
        for ( int x = 0;  x < in_W;  x++ )
        {
            for ( int y = 0;  y < in_H;  y++ )
            {
                //alphas[ pix ].r = (y < 256) ? x^y : 0;
                //alphas[ pix ].g = (y < 512) ? 127 : 0;
                //alphas[ pix ].b = (y < 768) ? 127 : 0;
                alphas[ pix ].a = (y < 512) ? x^y : 0; // half mottled, half black

                pix++;
            }
        }

        // set some params on the ACTIVE texture
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/  );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

        // WRITE/COPY from P into active texture  
        glTexImage2D( GL_TEXTURE_2D, 0,
                     GL_RGBA /*GL_ALPHA*/, in_W, in_H, 0, 
                     GL_RGBA /*GL_ALPHA*/, 
                     GL_UNSIGNED_BYTE, 
                     (void *) alphas );

        //glGenerateMipmap( GL_TEXTURE_2D );

        free( alphas );

        glLogAndFlushErrors();

    }


    GLuint textureFrameBuffer;
    {
        GLint oldFBO;
        glGetIntegerv( GL_FRAMEBUFFER_BINDING, & oldFBO );

        // create framebuffer
        glGenFramebuffers( 1, & textureFrameBuffer );
        glBindFramebuffer( GL_FRAMEBUFFER, textureFrameBuffer );

        // attach renderbuffer
        glFramebufferTexture2D( GL_FRAMEBUFFER, 
                               GL_COLOR_ATTACHMENT0, 
                               GL_TEXTURE_2D, 
                               id_texDest, 
                               0 );

        //glDisable( GL_DEPTH_TEST );

        // Test the framebuffer for completeness. This test only needs to be performed when the framebuffer’s configuration changes.
        GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER ) ;
        NSAssert1( status == GL_FRAMEBUFFER_COMPLETE, @"failed to make complete framebuffer object %x", status );

        // 36054  0x8CD6  GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

        // unbind frame buffer
        glBindFramebuffer( GL_FRAMEBUFFER, oldFBO );
    }




    glLogAndFlushErrors();

    // clear texture bitmap to backcolor
    {
        GLint oldFBO;
        glGetIntegerv( GL_FRAMEBUFFER_BINDING, & oldFBO );

        glBindFramebuffer( GL_FRAMEBUFFER, textureFrameBuffer );
        glLogAndFlushErrors();

        {
            float j = 0.1f;
            glClearColor( j, j, j, j );
            glLogAndFlushErrors();
            glClear( GL_COLOR_BUFFER_BIT );
            glLogAndFlushErrors();
        }

        glBindFramebuffer( GL_FRAMEBUFFER, oldFBO );
    }

    glDeleteFramebuffers( 1, & textureFrameBuffer );

    * out_pTexId = id_texDest;

    glLogAndFlushErrors();
}

I'm pretty sure now after hours of bashing that this cannot be done.

This is my code so far (BELOW) for rendering to a texture; it does the job, but is very wasteful. I only want a single 8-bit channel, possibly 16-bit greyscale. I don't want a useless R G and B channel.

But if I try to switch GL_RGBA /*GL_ALPHA*/ in glTexImage2D, glCheckFramebufferStatus catches a 'frame buffer incomplete' error: 36054 0x8CD6 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

guys on IRC suggest GL_R but Xcode doesn't offer autocompleteion for that, so it looks like maybe it is one of those things pruned out of GL for GLES

but that seems really bizarre! this is a mobile device. Surely something that reduces by a factor of four the amount of bits needed to perform an operation... surely this would be one of the last things to take out.

?!?

can anyone bury this one definitively? Is it possible to render onto a single channel texture in GLES2.0?

+ (void)  blurTexture: (GLuint)     in_texId
             POTWidth: (GLuint)     in_W
            POTHeight: (GLuint)     in_H
       returningTexId: (GLuint*)    out_pTexId
{
    // search HELP: 'Using a Framebuffer Object as a Texture'
    // http://stackoverflow.com/questions/3613889/gl-framebuffer-incomplete-attachment-when-trying-to-attach-texture

    // Create the destination texture, and attach it to the framebuffer’s color attachment point.

    // create the texture
    GLuint id_texDest;
    {
        // fragshader will use 0 
        glActiveTexture( GL_TEXTURE0 );

        // Ask GL to give us a texture-ID for us to use
        glGenTextures( 1, & id_texDest );
        glBindTexture( GL_TEXTURE_2D, id_texDest );


        // actually allocate memory for this texture
        GLuint pixCount = in_W * in_H;

        typedef struct { uint8_t r, g, b, a } rgba;

        rgba * alphas = calloc( pixCount, sizeof( rgba ) );

        // XOR texture
        int pix=0;
        for ( int x = 0;  x < in_W;  x++ )
        {
            for ( int y = 0;  y < in_H;  y++ )
            {
                //alphas[ pix ].r = (y < 256) ? x^y : 0;
                //alphas[ pix ].g = (y < 512) ? 127 : 0;
                //alphas[ pix ].b = (y < 768) ? 127 : 0;
                alphas[ pix ].a = (y < 512) ? x^y : 0; // half mottled, half black

                pix++;
            }
        }

        // set some params on the ACTIVE texture
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR/*_MIPMAP_LINEAR*/  );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

        // WRITE/COPY from P into active texture  
        glTexImage2D( GL_TEXTURE_2D, 0,
                     GL_RGBA /*GL_ALPHA*/, in_W, in_H, 0, 
                     GL_RGBA /*GL_ALPHA*/, 
                     GL_UNSIGNED_BYTE, 
                     (void *) alphas );

        //glGenerateMipmap( GL_TEXTURE_2D );

        free( alphas );

        glLogAndFlushErrors();

    }


    GLuint textureFrameBuffer;
    {
        GLint oldFBO;
        glGetIntegerv( GL_FRAMEBUFFER_BINDING, & oldFBO );

        // create framebuffer
        glGenFramebuffers( 1, & textureFrameBuffer );
        glBindFramebuffer( GL_FRAMEBUFFER, textureFrameBuffer );

        // attach renderbuffer
        glFramebufferTexture2D( GL_FRAMEBUFFER, 
                               GL_COLOR_ATTACHMENT0, 
                               GL_TEXTURE_2D, 
                               id_texDest, 
                               0 );

        //glDisable( GL_DEPTH_TEST );

        // Test the framebuffer for completeness. This test only needs to be performed when the framebuffer’s configuration changes.
        GLenum status = glCheckFramebufferStatus( GL_FRAMEBUFFER ) ;
        NSAssert1( status == GL_FRAMEBUFFER_COMPLETE, @"failed to make complete framebuffer object %x", status );

        // 36054  0x8CD6  GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

        // unbind frame buffer
        glBindFramebuffer( GL_FRAMEBUFFER, oldFBO );
    }




    glLogAndFlushErrors();

    // clear texture bitmap to backcolor
    {
        GLint oldFBO;
        glGetIntegerv( GL_FRAMEBUFFER_BINDING, & oldFBO );

        glBindFramebuffer( GL_FRAMEBUFFER, textureFrameBuffer );
        glLogAndFlushErrors();

        {
            float j = 0.1f;
            glClearColor( j, j, j, j );
            glLogAndFlushErrors();
            glClear( GL_COLOR_BUFFER_BIT );
            glLogAndFlushErrors();
        }

        glBindFramebuffer( GL_FRAMEBUFFER, oldFBO );
    }

    glDeleteFramebuffers( 1, & textureFrameBuffer );

    * out_pTexId = id_texDest;

    glLogAndFlushErrors();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

彩扇题诗 2024-11-15 18:07:12

从 iOS 5.0 开始,您可以使用 GL_EXT_texture_rg 渲染 1 通道纹理和 2 通道纹理。

http://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_rg.txt< /a>

http: //developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iOS5.html#//apple_ref/doc/uid/TP30915195-SW47

编辑:我已经测试过这个并且它有效,但仅限于 A5 及以上版本(iPad2/3/4/mini、iPhone4S/5、iPod touch 第 5 代)。不幸的是,它不适用于最需要的 A4 及更早版本(iPhone4、iPod touch 第 4 代、3GS、iPad1)。

Since iOS 5.0, you can render to both 1 and 2 channel textures using GL_EXT_texture_rg.

http://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_rg.txt

http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iOS5.html#//apple_ref/doc/uid/TP30915195-SW47

Edit: I've tested this and it works, but only on A5 and above (iPad2/3/4/mini, iPhone4S/5, iPod touch 5th gen). Unfortunately it's not available on A4 and older where it's needed most (iPhone4, iPod touch 4th gen, 3GS, iPad1).

反话 2024-11-15 18:07:12

不,OpenGL ES 2.0 没有任何可渲染的 1 通道纹理格式。 GL_ALPHA 和 GL_LUMINANCE 不可渲染,因此它们对于 RTT 毫无用处。

No, OpenGL ES 2.0 doesn't have any renderable 1-channel texture formats. GL_ALPHA and GL_LUMINANCE aren't renderable so they are useless for RTT.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文