在OpenGL中使用纹理/精灵的最佳方式(包括PBO)

我在C#中有一个小游戏,主要使用固定的精灵(从磁盘加载的位图)和一些视频。

现在我们目前的做法是

加载:

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);

画画

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);

和更新:

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);

所有的纹理都保存直到它们被使用,所以加载只在启动时进行一次(一般情况下)所以首先:对该方法的任何评论? 现在我想正确使用PBO来更新纹理(主要用于视频)A)使用PBO添加纹理(来自bmp)是一个好主意吗? 我会创建一个pbo,将数据从bmp复制到pbo,然后使用TexSubImage2D。 是否有任何性能点或者是高开销? B)更新相同:当前代码:

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);

这实际上工作还是没有收益?

我读了http://www.opengl.org/wiki/Pixel_Buffer_Object和http://www.songho.ca/opengl/gl_pbo.html以及关于下载和使用建议的第一篇文章,如果我上传数据和立即画出该纹理(甚至使用TexSubImage2D?),那么PBO不会再获得更高的速度。 这是正确的吗? 因此,如果我使用PBO,我将不得不使用第二个PBO并延迟一帧画框?

我的主循环是这样的:

{
  DoSomeInputHandling();
  CopyDecodedVideoFrameToTexture();
  DrawTexture();
}

在另一个线程中进行视频解码。

是一个非常天真的方法,但工作。 做这件事的正确/更好的方法是什么?


我的纹理创建和更新代码路径。 但有一件事:您不必在更新情况下重新指定纹理对象参数,如过滤器和换行模式,这些状态将保持原样。 使用即时模式进行绘图也不太可能导致最佳性能。

对于公益组织,可以避免额外的数据副本。 例如,您在另一个线程中的视频解码可以直接写入mappend PBO内存(当然,当线程想要写入对象时,您需要一些同步方案来保证对象被映射),因此请将您建议的额外副本在你的代码中。 实现PBO乒乓(或环形缓冲)方法可能会提高性能,并进一步分离单独的代码部分,但代价是延迟时间增加。 我不知道这是否是您的情况。

链接地址: http://www.djcxy.com/p/45737.html

上一篇: Best way of using textures/sprites in OpenGL (including PBO)

下一篇: PBO 2 way copy from and into the same FBO texture attachment