CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)
CSharpGL(42)借助帧缓存实现渲染到纹理(RenderToTexture)
渲染到纹理(Render To Texture)是实现很多OpenGL高级效果的一个基础。本文记录了如何用CSharpGL实现RTT。
下载
CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL)
开始
如图所示,我们把teapot贴到一个矩形上了。这是借助RTT实现的。
RTT步骤如下:
- 创建Framebuffer,这Framebuffer里包含一个Texture,这个Texture就是RTT里的Texture。
- 绑定Framebuffer,然后正常渲染,然后解绑Framebuffer。(RTT结束)
- 此时Framebuffer里包含的Texture已经有了想要的内容,我们可以像使用其他普通Texture一样使用此Texture。
创建Framebuffer
Framebuffer里包含若干renderbuffer和一个depthbuffer,就像VertexArrayObject里包含若干VertexBuffer和一个IndexBuffer。
创建Framebuffer过程概括如下:
1 private Framebuffer CreateFramebuffer(int width, int height) 2 { 3 var texture = new Texture(TextureTarget.Texture2D, 4 new NullImageFiller(width, height, GL.GL_RGBA, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE), 5 new SamplerParameters( 6 TextureWrapping.Repeat, 7 TextureWrapping.Repeat, 8 TextureWrapping.Repeat, 9 TextureFilter.Linear, 10 TextureFilter.Linear)); 11 texture.Initialize(); 12 this.BindingTexture = texture; 13 Renderbuffer colorBuffer = Renderbuffer.CreateColorbuffer(width, height, GL.GL_RGBA); 14 Renderbuffer depthBuffer = Renderbuffer.CreateDepthbuffer(width, height, DepthComponentType.DepthComponent24); 15 var framebuffer = new Framebuffer(); 16 framebuffer.Bind(); 17 framebuffer.Attach(colorBuffer);//0 18 framebuffer.Attach(texture);//1 19 framebuffer.Attach(depthBuffer);// special 20 framebuffer.SetDrawBuffers(GL.GL_COLOR_ATTACHMENT0 + 1);// as in 1 in framebuffer.Attach(texture);//1 21 framebuffer.CheckCompleteness(); 22 framebuffer.Unbind(); 23 return framebuffer; 24 }
使用Framebuffer
创建Framebuffer后,先绑定Framebuffer,再像平时一样渲染,再解绑Framebuffer。
1 public void RenderBeforeChildren(RenderEventArgs arg) 2 { 3 if (this.Width <= 0 || this.Height <= 0) { return; } 4 5 var viewport = new int[4]; 6 GL.Instance.GetIntegerv((uint)GetTarget.Viewport, viewport); 7 8 this.framebuffer = this.helper.GetFramebuffer(this.Width, this.Height); 9 framebuffer.Bind(); 10 GL.Instance.Viewport(0, 0, this.Width, this.Height); 11 { 12 int[] value = new int[4]; 13 GL.Instance.GetIntegerv((uint)GetTarget.ColorClearValue, value); 14 { 15 vec3 color = this.BackgroundColor.ToVec3(); 16 GL.Instance.ClearColor(color.x, color.y, color.z, 0.0f); // 0.0f for alpha channel, in case that transparent background is needed. 17 GL.Instance.Clear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT); 18 } 19 { 20 var args = new RenderEventArgs(this.Camera); 21 foreach (var item in this.Children) 22 { 23 RenderAction.Render(item, args); 24 } 25 } 26 { 27 GL.Instance.ClearColor(value[0], value[1], value[2], value[3]);// recover clear color. 28 } 29 } 30 GL.Instance.Viewport(viewport[0], viewport[1], viewport[2], viewport[3]);// recover viewport. 31 this.framebuffer.Unbind(); 32 }
使用RTT
此时Framebuffer里包含的Texture已经有了想要的内容,我们可以像使用其他普通Texture一样使用此Texture。例如本文开始处将Texture贴到一个矩形上。
当然也可以结合Billboard的需求,把Texture贴到Billboard上。
总结
最近几个月我在尝试修整CSharpGL,感觉好多了。
微信扫码,自愿捐赠。天涯同道,共谱新篇。
微信捐赠不显示捐赠者个人信息,如需要,请注明联系方式。 |