【发布时间】:2017-08-03 11:55:49
【问题描述】:
OpenGL中glframebuffertexture和glbindtexture这两个函数的具体使用区别是什么。
具体来说,我正在使用 OpenTK 为嵌入式机器编写一个使用 OpenGL 的自定义轻量级 UI,该嵌入式机器为 UI 中的不同组件使用大量帧缓冲区和各自的纹理。在内部使用堆栈跟踪帧缓冲区,因为缓冲区内容可以被绘制到“父”缓冲区(或者如果没有父缓冲区,则屏幕空间)。
我很难以正确的顺序进行调用,我想知道我是否对何时需要将纹理绑定到帧缓冲区以及何时需要将纹理分配给帧缓冲区感到困惑。
我已阅读有关这些函数的文档,但它们并没有真正解释这些函数在其上下文中与帧缓冲区之间的关系。
我基本上没有任何东西被渲染回屏幕。
例如,如果我使用 SharpFont(FreeType 绑定库)渲染文本,我有一个用于整个渲染字符串的帧缓冲区和一个用于渲染每个字符的帧缓冲区。
这是我认为在此示例中进行调用的一般顺序
从 FB0(屏幕空间)开始,
创建 FB 1,
使用 TX 1 设置 FB 1(绑定到 FB 1)(创建然后绑定到然后附加),
绑定回FB0,
绑定到 FB1(开始渲染到),
创建 FB2,
使用 TX 2 设置 FB 2(绑定到 FB 2)(创建然后绑定到然后附加),(包括渲染的字符像素数据),
绑定回 FB1,
绑定到 TX2
使用四边形渲染 TX2(假设)
在 7 点重复下一个字符直到结束
绑定回 FB0
使用四边形渲染 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);
}
【问题讨论】: