robpson's picture

Rubberband drawing and static backbuffer

1) I'm creating a CAD like application. A single scene rendering might contains hundreds of thousands of lines and cannot be drawn in realtime when the paint event occurs. What I want to do is rendering to a static buffer, which I can blit/swap to the front buffer when a paint event occurs. The problem with SwapBuffers is that it seems to destroy the contents of the backbuffer, even in windowed mode. What is the best way to work this out?

2) I need some nice xor:ed rubberboxes (for object selection etc.). I can do this by setting GL.DrawBuffer to frontbuffer and GL.LogicOp to xor. However xor mode seems to work only in indexed color mode. Indexed color mode should be ok for me, if it wasnt for that hardware acceleration does not work if color depth is another than the physical screens. This makes indexed mode very slow. Any suggestions on how to use OpenGL to draw nice rubberlines/boxes using opengl?

/Rob.P.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Kamujin's picture

I have a similar issue with a GUI app I am writing. For performance reasons, I don't want to recreate every "window" each time I draw a frame.

To speed things up, I render each "window" in my GUI app to a Framebuffer. Then when I render to the screen, I can access the texture of the frame buffer and use that to texture a quad. I use alpha transparency to deal with non-rectangular windows. The performance improvement is quite impressive as long as your not re-rendering the framebuffer's texture each frame.

Here is some code I use to create / manage my framebuffer. This should give you a decent idea what to read in the OpenGL spec to get more info.

	public class FrameBuffer : IDisposable
	{
		public readonly uint handleFrameBuffer;
		public readonly uint handleTexture;
		public readonly uint handleDepth;
 
		public readonly int width;
		public readonly int height;
 
		public FrameBuffer(int width, int height)
		{		
			this.width = width;
			this.height = height;
 
			GL.GenTextures(1, out handleTexture);
			GL.BindTexture(TextureTarget.Texture2D, handleTexture);
			GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
			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.ClampToBorder);
		        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder);
 
			GL.GenTextures(1, out handleDepth);
		        GL.BindTexture(TextureTarget.Texture2D, handleDepth );
		        GL.TexImage2D(TextureTarget.Texture2D, 0, (PixelInternalFormat) All.DepthComponent32, width, height, 0, PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
		        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.ClampToBorder);
		        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder);
 
			GL.Ext.GenFramebuffers(1, out handleFrameBuffer);
			GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, handleFrameBuffer);
			GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, handleTexture, 0);
			GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, TextureTarget.Texture2D, handleDepth, 0);
 
			FramebufferErrorCode errorCode = GL.Ext.CheckFramebufferStatus(FramebufferTarget.FramebufferExt);
 
			if(errorCode != FramebufferErrorCode.FramebufferCompleteExt)
			{
				throw new Exception(string.Format("Framebuffer construction failed with error: {0}", errorCode));
			}
		}
 
		public void Use()
		{
			GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, this.handleFrameBuffer);
			GL.Viewport(0, 0, width, height);
		}
 
		public static void UseDefault(int viewportWidth, int viewportHeight)
		{
			GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);
			GL.Viewport(0, 0, viewportWidth, viewportHeight);
		}
 
		public void Dispose()
		{
			uint value;
 
			value = this.handleFrameBuffer; GL.Ext.DeleteFramebuffers(1, ref value);
			value = this.handleDepth; GL.DeleteTextures(1, ref value);
			value = this.handleTexture; GL.DeleteTextures(1, ref value);
		}
 
		private Matrix4 viewMatrix;
		public Matrix4 ViewMatrix
		{
			get
			{
				return viewMatrix;
			}
			set
			{
				viewMatrix = value;
			}
		}
 
		private Matrix4 projectionMatrix;
		public Matrix4 ProjectionMatrix
		{
			get
			{
				return projectionMatrix;
 
			}
			set
			{
				projectionMatrix = value;
			}
		}
	}