【问题标题】:Difference between glframebuffertexture and glbindtextureglframebuffertexture 和 glbindtexture 的区别
【发布时间】:2017-08-03 11:55:49
【问题描述】:

OpenGL中glframebuffertextureglbindtexture这两个函数的具体使用区别是什么。

具体来说,我正在使用 OpenTK 为嵌入式机器编写一个使用 OpenGL 的自定义轻量级 UI,该嵌入式机器为 UI 中的不同组件使用大量帧缓冲区和各自的纹理。在内部使用堆栈跟踪帧缓冲区,因为缓冲区内容可以被绘制到“父”缓冲区(或者如果没有父缓冲区,则屏幕空间)。

我很难以正确的顺序进行调用,我想知道我是否对何时需要将纹理绑定到帧缓冲区以及何时需要将纹理分配给帧缓冲区感到困惑。

我已阅读有关这些函数的文档,但它们并没有真正解释这些函数在其上下文中与帧缓冲区之间的关系。

我基本上没有任何东西被渲染回屏幕。

例如,如果我使用 SharpFont(FreeType 绑定库)渲染文本,我有一个用于整个渲染字符串的帧缓冲区和一个用于渲染每个字符的帧缓冲区。

这是我认为在此示例中进行调用的一般顺序

  1. 从 FB0(屏幕空间)开始,

  2. 创建 FB 1,

  3. 使用 TX 1 设置 FB 1(绑定到 FB 1)(创建然后绑定到然后附加),

  4. 绑定回FB0,

  5. 绑定到 FB1(开始渲染到),

  6. 创建 FB2,

  7. 使用 TX 2 设置 FB 2(绑定到 FB 2)(创建然后绑定到然后附加),(包括渲染的字符像素数据),

  8. 绑定回 FB1,

  9. 绑定到 TX2

  10. 使用四边形渲染 TX2(假设)

  11. 在 7 点重复下一个字符直到结束

  12. 绑定回 FB0

  13. 使用四边形渲染 TX1(假设)。


FrameBuffer(UI 对象)

    public class OGLFrameBuffer : IFrameBuffer {

    private int frameBufferId = -1;
    private int frameBufferTexture = -1;

    private IDrawer ctx;

    public OGLFrameBuffer(IDrawer dCtx) { ctx = dCtx; }

    public void SetupFrameBuffer(float width, float height) {

        //Generate Frame Buffer if not exists;
        if (frameBufferId == -1) {
            frameBufferId = GL.GenFramebuffer();
        }

        //set current frame buffer
        ctx.PushUseFrameBuffer(this, new Size((int)Math.Ceiling(width), (int)Math.Ceiling(height)));

        if (frameBufferTexture != -1)
            GL.DeleteTexture(frameBufferTexture);

        //Generate Texture with buffer size;
        frameBufferTexture = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, frameBufferTexture);

        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)Math.Ceiling(width), (int)Math.Ceiling(height), 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);

        GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, frameBufferTexture, 0);

        //return to previous buffer
        ctx.PopFrameBuffer();

    }

    public void SetupFrameBuffer(float width, float height, byte[] data, VIPixelFormat pixelFormat) {

        PixelFormat oglPixFmt;

        switch (pixelFormat) {
            case VIPixelFormat.VIPF_RGBA:
                oglPixFmt = PixelFormat.Bgra;
                break;
            case VIPixelFormat.VIPF_GREYSCALE:
                oglPixFmt = PixelFormat.Red;
                break;
            case VIPixelFormat.VIPF_RGB:
            default:
                oglPixFmt = PixelFormat.Bgr;
                break;
        }

        //Generate Frame Buffer if not exists;
        if (frameBufferId == -1) {
            frameBufferId = GL.GenFramebuffer();               
        }

        //set current frame buffer
        ctx.PushUseFrameBuffer(this, new Size((int)Math.Ceiling(width), (int)Math.Ceiling(height)));

        if (frameBufferTexture != -1)
            GL.DeleteTexture(frameBufferTexture);

        //Generate Texture with buffer size;
        frameBufferTexture = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, frameBufferTexture);

        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);

        if (pixelFormat == VIPixelFormat.VIPF_GREYSCALE) {
            //GL.ClearColor(1f, 1f, 1f, 1f);
            //GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        }

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, (int)Math.Ceiling(width), (int)Math.Ceiling(height), 0, oglPixFmt, PixelType.UnsignedByte, data);

        GL.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, frameBufferTexture, 0);

        //return to previous buffer
        ctx.PopFrameBuffer();

    }

    public int GetFrameBufferId() {
        return frameBufferId;
    }

    public int GetFrameBufferTexture() {
        return frameBufferTexture;
    }
}

相关上下文调用:

        public void PushUseFrameBuffer(IFrameBuffer buf, Size bufferDims) {
        frameBufferStack.Push(buf);
        OGLFrameBuffer frameBuf = (OGLFrameBuffer)buf;
        GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBuf.GetFrameBufferId());
        ctxbounds = new Rectangle(new Point(0, 0), bufferDims);
    }

    public void PopFrameBuffer() {
        frameBufferStack.Pop();

        if (frameBufferStack.Count != 0) {
            OGLFrameBuffer frameBuf = (OGLFrameBuffer)frameBufferStack.Peek();
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, frameBuf.GetFrameBufferId());
        }
        else {
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
        }

        ctxbounds = windowbounds;
    }

public void DrawBuffer(IFrameBuffer buff, RectangleF textureBounds, Size parentBounds) {

        OGLFrameBuffer toDrawFb = (OGLFrameBuffer)buff;

        GL.BindTexture(TextureTarget.Texture2D, toDrawFb.GetFrameBufferTexture());

        GL.Begin(PrimitiveType.Quads);

        GL.TexCoord2(0.0f, 1.0f); GL.Vertex2((textureBounds.X * scale)                         / parentBounds.Width , (textureBounds.Y * scale)                          / parentBounds.Height);
        GL.TexCoord2(1.0f, 1.0f); GL.Vertex2(((textureBounds.X + textureBounds.Width) * scale) / parentBounds.Width , (textureBounds.Y * scale)                          / parentBounds.Height);
        GL.TexCoord2(1.0f, 0.0f); GL.Vertex2(((textureBounds.X + textureBounds.Width) * scale) / parentBounds.Width , ((textureBounds.Y + textureBounds.Height) * scale) / parentBounds.Height);
        GL.TexCoord2(0.0f, 0.0f); GL.Vertex2((textureBounds.X * scale)                         / parentBounds.Width , ((textureBounds.Y + textureBounds.Height) * scale) / parentBounds.Height);

        GL.End();

        OGLFrameBuffer curFb = (OGLFrameBuffer)GetCurrentFrameBuffer();

        if (curFb != null) {
            GL.BindTexture(TextureTarget.Texture2D, curFb.GetFrameBufferTexture());
        }
        else {
            GL.BindTexture(TextureTarget.Texture2D, 0);
        }

        SetColour(1, 1, 1, 1f);
        DrawRectangle(textureBounds);
    }

【问题讨论】:

    标签: c# opengl


    【解决方案1】:

    glFrameBufferTexture 将纹理关联到帧缓冲区作为渲染目标。

    这意味着当你发出一个drawcall时,这个纹理将被你的片段着色器的输出写入(如果启用了混合)。

    GlBindTexture 告诉 OpenGL 你想读取这个纹理(例如通过 sampler2D)

    简单地说:glFrameBufferTexture 允许你渲染(或写入)这个纹理而不是你自己的屏幕,glBindTexture 允许你读取纹理内的数据(它可以是你写的纹理,感谢帧缓冲区,或者你的纹理加载图像时写的)。

    编辑:更一般地说,在 OpenGL 中绑定一个对象会告诉 OpenGL 它将使用该对象进行所有后续操作。

    当你想做一个 glTexParameter 时,你必须先绑定你正在处理的纹理。或使用 DSA; glTextureParameter/

    缓冲区和其他对象是一样的

    【讨论】:

    • 在查看了如何使用纹理设置帧缓冲区的教程后,它们绑定到纹理,然后调用 glTexParameter。那么在这种情况下真的需要调用 glBindTexture 吗?由于我实际上并没有阅读纹理,因此我有效地对其进行了更改。
    • 是的,技术上绑定意味着使用(读取)或更改设置(不进行绘图调用)。因此,如果我的帧缓冲区当前绑定到另一个纹理并且我在 0 处绑定回缓冲区,这是否意味着帧缓冲区不再引用任何纹理以供使用,或者纹理名称 0 是在 opengl 初始化时分配的默认纹理时间?
    • GlBind To 0 表示您不想再绑定对象了。
    猜你喜欢
    • 2012-02-10
    • 2016-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2011-10-20
    相关资源
    最近更新 更多