CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)

渲染到纹理(Render To Texture)是实现很多OpenGL高级效果的一个基础。本文记录了如何用CSharpGL实现RTT。

下载

CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

开始

CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)-LMLPHP

CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)-LMLPHP

CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)-LMLPHP

如图所示,我们把teapot贴到一个矩形上了。这是借助RTT实现的。

RTT步骤如下:

  1. 创建Framebuffer,这Framebuffer里包含一个Texture,这个Texture就是RTT里的Texture。
  2. 绑定Framebuffer,然后正常渲染,然后解绑Framebuffer。(RTT结束)
  3. 此时Framebuffer里包含的Texture已经有了想要的内容,我们可以像使用其他普通Texture一样使用此Texture。

创建Framebuffer

Framebuffer里包含若干renderbuffer和一个depthbuffer,就像VertexArrayObject里包含若干VertexBuffer和一个IndexBuffer。

创建Framebuffer过程概括如下:

         private Framebuffer CreateFramebuffer(int width, int height)
{
var texture = new Texture(TextureTarget.Texture2D,
new NullImageFiller(width, height, GL.GL_RGBA, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE),
new SamplerParameters(
TextureWrapping.Repeat,
TextureWrapping.Repeat,
TextureWrapping.Repeat,
TextureFilter.Linear,
TextureFilter.Linear));
texture.Initialize();
this.BindingTexture = texture;
Renderbuffer colorBuffer = Renderbuffer.CreateColorbuffer(width, height, GL.GL_RGBA);
Renderbuffer depthBuffer = Renderbuffer.CreateDepthbuffer(width, height, DepthComponentType.DepthComponent24);
var framebuffer = new Framebuffer();
framebuffer.Bind();
framebuffer.Attach(colorBuffer);//
framebuffer.Attach(texture);//
framebuffer.Attach(depthBuffer);// special
framebuffer.SetDrawBuffers(GL.GL_COLOR_ATTACHMENT0 + );// as in 1 in framebuffer.Attach(texture);//
framebuffer.CheckCompleteness();
framebuffer.Unbind();
return framebuffer;
}

使用Framebuffer

创建Framebuffer后,先绑定Framebuffer,再像平时一样渲染,再解绑Framebuffer。

         public void RenderBeforeChildren(RenderEventArgs arg)
{
if (this.Width <= || this.Height <= ) { return; } var viewport = new int[];
GL.Instance.GetIntegerv((uint)GetTarget.Viewport, viewport); this.framebuffer = this.helper.GetFramebuffer(this.Width, this.Height);
framebuffer.Bind();
GL.Instance.Viewport(, , this.Width, this.Height);
{
int[] value = new int[];
GL.Instance.GetIntegerv((uint)GetTarget.ColorClearValue, value);
{
vec3 color = this.BackgroundColor.ToVec3();
GL.Instance.ClearColor(color.x, color.y, color.z, 0.0f); // 0.0f for alpha channel, in case that transparent background is needed.
GL.Instance.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);
}
{
var args = new RenderEventArgs(this.Camera);
foreach (var item in this.Children)
{
RenderAction.Render(item, args);
}
}
{
GL.Instance.ClearColor(value[], value[], value[], value[]);// recover clear color.
}
}
GL.Instance.Viewport(viewport[], viewport[], viewport[], viewport[]);// recover viewport.
this.framebuffer.Unbind();
}

使用RTT

此时Framebuffer里包含的Texture已经有了想要的内容,我们可以像使用其他普通Texture一样使用此Texture。例如本文开始处将Texture贴到一个矩形上。

CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)-LMLPHP

当然也可以结合Billboard的需求,把Texture贴到Billboard上。CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)-LMLPHP

总结

最近几个月我在尝试修整CSharpGL,感觉好多了。

05-11 11:26