Best way of using textures/sprites in OpenGL (including PBO)
I have a little game in C# which uses mainly fixed sprites (bitmaps loaded from disk) and some videos.
Now our current approach is
Loading:
texture.ID = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, texture.ID);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, w, h, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
Drawing
GL.BindTexture(TextureTarget.Texture2D, texture.ID);
GL.MatrixMode(MatrixMode.Texture);
GL.PushMatrix();
GL.Begin(BeginMode.Quads);
GL.TexCoord2(x1, y1);
GL.Vertex3(rx1, ry1, rect.Z);
GL.TexCoord2(x1, y2);
GL.Vertex3(rx1, ry2, rect.Z);
GL.TexCoord2(x2, y2);
GL.Vertex3(rx2, ry2, rect.Z);
GL.TexCoord2(x2, y1);
GL.Vertex3(rx2, ry1, rect.Z);
GL.End();
GL.PopMatrix();
GL.BindTexture(TextureTarget.Texture2D, 0);
And Updating:
GL.BindTexture(TextureTarget.Texture2D, texture.ID);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, data);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D);
GL.BindTexture(TextureTarget.Texture2D, 0);
All the textures are kept till they are used, so loading is only done once at startup (in general) So first: Any comments on that method? Now I'd want to use PBO properly to update the textures (mainly for video) A) Is it a good idea to use a PBO to add the texture (from bmp)? I'd create a pbo, copy data from bmp to pbo and then use TexSubImage2D. Are there any performance points for that or is the overhead to high? B) Same for updating: Current Code:
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, texture.PBO);
IntPtr buffer = GL.MapBuffer(BufferTarget.PixelUnpackBuffer, BufferAccess.WriteOnly);
Marshal.Copy(data, 0, buffer, data.Length);
GL.UnmapBuffer(BufferTarget.PixelUnpackBuffer);
GL.BindTexture(TextureTarget.Texture2D, texture.ID);
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, w, h, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
Does this actually work or is there no benefit with that?
I read http://www.opengl.org/wiki/Pixel_Buffer_Object and http://www.songho.ca/opengl/gl_pbo.html and the first article about the download-and-use suggest, that if I upload data and immediately draw that texture (or even use TexSubImage2D?) then I won't get any more speed by the PBO. Is this right? So if I use the PBO would I have to use a 2nd PBO and draw the frames a frame delayed?
My main-loop is like:
{
DoSomeInputHandling();
CopyDecodedVideoFrameToTexture();
DrawTexture();
}
With video decoding in another thread.
Is a pretty naive approach but working. What's the correct/better way of doing this?
Your texture creation and update code paths OK to me. One thing, though: you don't have to respecify the texture object parameters like filters and wrap modes int the update case, those states will stay as they are. Using immediate mode for drawing is also not likely to lead to optimal performance.
With PBOs one can avoid extra copies of the data. For example, your video decoding in another thread could directly write into mappend PBO memory (you will of course need some synchronization scheme to guarantee that the object is mapped when the thread wants to write to it), so eleminate the extra copy you are suggesting in your code. Implementing a PBO ping-pong (or ring buffer) approach might increase the performance and further disentangle the separate code parts, but at the cost of increaed latency. I don't know if this is a concern for your scenario.
链接地址: http://www.djcxy.com/p/45738.html上一篇: OpenGL PBO纹理上传怪异