【 OpenGL 教程07 】在 OpenGL 中读取纹理缓冲区

目录

一、说明

        纹理是的object不是buffer,而是特定类型的对象。 OpenGL 术语中进行这种区分是为了消除任何混淆。纹理对象如容器,它包含数据存储buffer,同样的,缓冲区对象也包含数据存储buffer。本文将对此诸多概念拨云见日,指出上山之道路,不再为困。

二、(OpenGL) 如何读回纹理缓冲区?

2.1 问题针对:

        函数 glGetBufferSubData 是否适用于纹理缓冲区和常规缓冲区?我目前正在尝试诊断为什么我的纹理没有出现,并且在利用 glGetBufferSubData 检查缓冲区时,我收到了无意义的信息。

struct TypeGLtexture //Associate texture data with a GL buffer
{
    TypeGLbufferID GLbuffer;
    TypeImageFile  ImageFile;
    void GenerateGLbuffer   ()
    {
        if (GLbuffer.isActive==true || ImageFile.GetPixelArray().size()==0) return;
        GLbuffer.isActive=true;
        GLbuffer.isTexture=true;
        GLbuffer.Name="Texture Buffer";
        GLbuffer.ElementCount=ImageFile.GetPixelArray().size();
        glEnable(GL_TEXTURE_2D);
        glGenTextures (1,&GLbuffer.ID);              //instantiate ONE buffer object and return its handle/ID
        glBindTexture (GL_TEXTURE_2D,GLbuffer.ID);   //connect the object to the GL_TEXTURE_2D docking point
        glTexImage2D (GL_TEXTURE_2D,0,GL_RGB,ImageFile.GetProperties().width, ImageFile.GetProperties().height,0,GL_RGB,GL_UNSIGNED_BYTE,&(ImageFile.GetPixelArray()[0]));
if(ImageFile.GetProperties().width==6){
    cout<<"Actual Data"<

应用后  glGetTexImage(GL_TEXTURE_2D,0,GL_RGB,GL_UNSIGNED_BYTE,read);  ,数据显示变化,如 中所示:

2.2 解决方案

        是的,这适用于纹理缓冲区,如果这实际上是其中之一的话。

        该glGetBufferSubData (...)  函数迎合缓冲区对象。然而,在这种情况下,您正在处理一个纹理对象。如果您尝试使用 API  glGetError (...)  来验证错误状态,您可能会收到 API 错误。这是因为  GL_TEXTURE_2D  不是纹理对象缓冲区目标。

        遗憾的是,术语似乎存在混淆。此外,还存在一种缓冲区纹理,它是一种独特的 1D 纹理,使您能够将缓冲区对象用作受限类型的纹理。

        建议不要宽松地使用术语“缓冲区”,而应将其视为“数据存储”。 OpenGL 也使用这个术语来防止任何混淆。纹理对象和缓冲区对象都有自己的数据存储。需要注意的是,除非您创建纹理缓冲区对象将它们链接在一起,否则这两个概念是分开的。

2.3 从纹理对象读回数据比这复杂得多。

        在OpenGL中,在访问像素数据之前需要定义像素格式和数据类型。出于兼容性的目的,OpenGL 将数据从纹理的内部格式转换为请求的格式。因此,您需要寻找具有以下签名的函数。

void glGetTexImage (GLenum      target,
                    GLint       level,
                    GLenum      format, // GL will convert to this format
                    GLenum      type,   // Using this data type per-pixel
                    GLvoid *    img);

        对于任何保存像素数据的 OpenGL 对象,您可以使用像素缓冲区对象将数据从纹理对象移动到不同的缓冲区对象。一旦您在像素缓冲区对象中获得了数据,您就可以  glGetBufferSubData (...)  按照原来的意图使用。

        如何在 openGL 中使用textureID 获取纹理数据,在 4.5+ OpenGL 中,可以通过使用 glGetTextureImage() 函数提供纹理 ID 来访问纹理数据。例如,为了获取 GL_RGB 纹理数据,我们有 3 个浮点数 R、G、B,每个浮点数都是 4 个字节,因此:

伊生代

三、从 SurfaceTexture 获取 OpenGL 纹理句柄

3.1 问题针对

        可以使用 SurfaceTexture 的 AttachToGLContext() 方法设置纹理句柄。 https://developer.android.com/reference/android/graphics/Sur​​faceTexture.html#attachToGLContext(int) 上的文档对此进行了解释。

        获取纹理句柄似乎是不可能的,除非您拥有对可以初始化它的代码的权限。

        要将 gl_texture_external_oes 纹理复制到 RGB GL_TEXTURE_2D,我需要纹理 ID。否则,我将不得不在TextureView 上使用GetBitmap,这会导致GPU 到CPU,然后返回GPU 复制。如果我可以直接在 OpenGL 中复制,就可以避免这个过程。

 

3.2 解决方案:

        要在 OpenGL ES 上下文中建立外部图像和纹理名称之间的连接,必须首先调用  glGenTextures()  生成纹理名称,然后使用  SurfaceTexture.attachToGLContext(int texName)  将图像绑定到它。

        完成初始步骤后,可以通过外部采样器在着色器中使用 SurfaceTexture,从而无需创建新纹理。避免将其转换为仅使用一次的算法的新纹理,因为这在带宽和功耗方面效率低下。

        Opengl - 通过纹理 ID 获取纹理目标,从 OpenGL 4.5 开始,可以通过以下方式完成:GLenum target; glGetTextureParameteriv(textureId, GL_TEXTURE_TARGET, (GLint*)&target);确实,自从 OpenGL 4.5 中引入直接状态访问 API (DSA) 以来,了解纹理的目标变得不再那么有用。

四、 如何使用 gstreamer crates 从 BufferRef 中提取 GL 纹理 id?

4.1 问题针对

        我当前的项目涉及利用 GL 将视频帧显示到纹理映射的网格上。在此之前,我已经成功创建了一个可处理单个 PNG 图像的 GL 应用程序。目前,我的目标是使用 gstreamer 解码视频。

        我从 appsink 示例开始。

        成功将解码的视频通过管道传输  glupload  到 appsink 后,下一步是将  BufferRef  获得的 转换 appsink.pull_sample().get_buffer()  为 GL 纹理 id (a  u32  ),以便可以将其传递给 GL 函数,例如  gl::BindTexture(gl::TEXTURE_2D, tex)  .为了实现这一点,  set_caps()  在 appsink 上使用,以确保缓冲区具有所需的功能  memory:GLMemory  ,并且是纹理而不是 GPU 外的缓冲区。

  gstreamer  在 Rust 中,在和 等板条箱的帮助下  gstreamer-*  ,从 a 获取 GL 纹理 id 的过程是什么  BufferRef  ?

 

4.2 解决方案一:

        为了从  GstGLMemory  C 中的 a 中检索纹理,需要  GstGLMemory  使用特殊  GST_MAP_GL  标志来映射 a 。然而,这种映射 OpenGL 纹理的特定方法在 Rust 中尚不可用。尽管如此,相关领域仍在开展工作,以改善 Rust 中 GStreamer OpenGL 使用情况,可以在 https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/581 中找到。

        要获得对纹理的可读访问,您可以利用  VideoFrameGLExt  上找到的 扩展特征 VideoFrame  。存储库中的 glupload 示例可以看到一个实际示例  gstreamer-rs  ,该示例使用  VideoFrameGLExt  .该  VideoFrameGLExt  特征目前已在  VideoFrame  .

        以下代码预计可用于以只读模式访问数据。

// buffer: gst::Buffer
// info: gst::VideoInfo
if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) {
    if let Some(texture) = frame.get_texture_id(0) {
        // use texture somehow
    }
}

        如果还需要写入纹理,则需要写入手动绑定,因为它当前未公开。

4.3 解决方案2:

最终起作用的代码是。

fn get_gl_memory(bref: &BufferRef, idx: u32) -> Option<*mut GstGLMemory> {
    unsafe {
        let n = gst_sys::gst_buffer_n_memory(bref.as_ptr() as *mut _);
        if idx >= n {
            return None;
        }
        let mem = gst_sys::gst_buffer_peek_memory(bref.as_ptr() as *mut _, idx);
        if 0 != gst_gl_sys::gst_is_gl_memory(mem) {
            Some(mem as *mut _)
        } else {
            None
        }
    }
}
//
let gl_mem = get_gl_memory(buffer, 0).unwrap();
let gl_mem = unsafe { &*gl_mem };
let tex_id = gl_mem.tex_id;

        只要您能够轻松到达 .ystreet00 提供的解决方案就是有效的  gst::VideoInfo  。

        (OpenGL)如何读回纹理缓冲区?,从纹理对象读回数据比这复杂得多。在从 OpenGL 中读取像素数据之前,您必须定义像素格式和数据类型。 OpenGL 旨在将数据从纹理的内部格式转换为您请求的任何(兼容)格式。

五、Android OpenGLES从textureID获取cloor数据

5.1 问题针对

        我的问题涉及从 Android 上的textureID 获取颜色数据。

        我的目的是利用 openGLES 获取真实的像素数据并随后对其进行更改。

        Gallerydata 包含我的代码,除了 glgeterror 的值为 0 之外,所有字节均为零。

        我不确定原因。有才华横溢的人可以帮助我吗?

byte[] Galleydata = new byte[GalleyWidth*GalleyHeight*4];
ByteBuffer buffer = ByteBuffer.wrap(Galleydata);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturePtr);
GLES20.glReadPixels(0,0,GalleyWidth,GalleyHeight,GLES20.GL_RGBA,GLES20.GL_UNSIGNED_BYTE,buffer);
buffer.get(Galleydata);

5.2 解决方案

        该函数  glReadPixels  从帧缓冲区检索像素。要使用此功能,您必须首先使用任何  glDraw*  方法渲染纹理。通常,您需要渲染两个三角形,因为四边形没有得到广泛支持,并且它们的支持仅限于扩展。

         从SurfaceTexture获取OpenGL纹理句柄,您需要通过调用glGenTextures()在OpenGL ES上下文中创建纹理名称,然后调用SurfaceTexture.attachToGLContext(int texName)将外部图像绑定到该纹理名称。脚注:完成后,您可以通过使用...在着色器中天真地使用 SurfaceTexture

Opengl: Reading Texture Buffer in OpenGL: A Guide

  • 39
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无水先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值