1

我有两个 VBO。其中一个有纹理,另一个没有。我没有成功地将它们同时绘制到屏幕上。DrawQuad 绘制无纹理的,DrawQuadTex 绘制有纹理的,两者的代码类似于以下:

// Enable/Disable GL_TEXTURE_2D depending on which I'm drawing
// Bind/Unbind the texture

GL.EnableClientState(ArrayCap.VertexArray);
GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
GL.VertexPointer(2, VertexPointerType.Float, Vector2.SizeInBytes, IntPtr.Zero);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);

GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);

无论首先调用这两个函数中的哪一个,该形状都是可见的(即,如果我调用 DrawQuad,那么一个无纹理的四边形是可见的)。

我确实在 GL_TEXTURE_2D 上设置了 glDisable 并尝试关闭 TexCoordArray 并尝试将纹理绑定到 0,但没有任何区别。有什么我忽略的吗?

SSCCE

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace E04
{
    internal class Renderer
    {
        private readonly Int32 _vertexBufferId;
        private readonly Int32 _textureBufferId;
        private readonly Int32 _indexBufferId;
        private readonly Int32 _colorBufferId;
        private readonly Int32 _normalBufferId;

        private readonly Vector2[] _vertices;
        private readonly Vector2[] _textureCoordinates;
        private readonly Byte[] _indices;
        private readonly Vector4[] _colors;
        private readonly Vector3[] _normals;

        public Renderer()
        {
            // Create a vertex array
            _vertices = new Vector2[4];

            // Set the coordinate data
            _textureCoordinates = new Vector2[4];
            _textureCoordinates[0].X = 0.0f;
            _textureCoordinates[0].Y = 0.0f;
            _textureCoordinates[1].X = 1.0f;
            _textureCoordinates[1].Y = 0.0f;
            _textureCoordinates[2].X = 0.0f;
            _textureCoordinates[2].Y = 1.0f;
            _textureCoordinates[3].X = 1.0f;
            _textureCoordinates[3].Y = 1.0f;

            // Set the index data
            _indices = new Byte[6];
            _indices[0] = 0;
            _indices[1] = 1;
            _indices[2] = 3;
            _indices[3] = 3;
            _indices[4] = 2;
            _indices[5] = 0;

            // Set the color data
            _colors = new Vector4[4];
            _colors[0] = new Vector4(1.0f, 0.0f, 0.0f, 1.0f);
            _colors[1] = new Vector4(1.0f, 1.0f, 0.0f, 1.0f);
            _colors[2] = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
            _colors[3] = new Vector4(0.0f, 0.0f, 1.0f, 1.0f);

            // Set the normal data
            _normals = new Vector3[4];
            _normals[0] = new Vector3(0.0f, 0.0f, 1.0f);
            _normals[1] = new Vector3(0.0f, 0.0f, 1.0f);
            _normals[2] = new Vector3(0.0f, 0.0f, 1.0f);
            _normals[3] = new Vector3(0.0f, 0.0f, 1.0f);

            // Bind the texture array buffer
            GL.GenBuffers(1, out _textureBufferId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_textureCoordinates.Length*Vector2.SizeInBytes),
                          _textureCoordinates, BufferUsageHint.DynamicDraw);
            GL.TexCoordPointer(2, TexCoordPointerType.Float, 8, IntPtr.Zero);
            GL.EnableClientState(ArrayCap.TextureCoordArray);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            // Bind the normal array buffer
            GL.GenBuffers(1, out _normalBufferId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_normals.Length*Vector3.SizeInBytes), _normals,
                          BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            // Bind the color array buffer
            GL.GenBuffers(1, out _colorBufferId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_colors.Length*Vector4.SizeInBytes), _colors,
                          BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            // Bind vertex array buffer
            GL.GenBuffers(1, out _vertexBufferId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (_vertices.Length*Vector2.SizeInBytes), _vertices,
                          BufferUsageHint.StreamDraw);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

            // Bind index array buffer
            GL.GenBuffers(1, out _indexBufferId);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);
            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (_indices.Length*sizeof (Byte)), _indices,
                          BufferUsageHint.StaticDraw);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
        }

        public void DrawQuad(Int32 x, Int32 y, Int32 width, Int32 height)
        {
            UpdateQuadVertices(x, y, width, height);

            GL.Disable(EnableCap.Texture2D);
            GL.BindTexture(TextureTarget.Texture2D, 0);

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.ColorArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
            GL.VertexPointer(2, VertexPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
            GL.ColorPointer(4, ColorPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
            GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
            GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);

            GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);
        }

        public void DrawQuadTex(Int32 x, Int32 y, Int32 width, Int32 height, Int32 textureId)
        {
            UpdateQuadVertices(x, y, width, height);

            GL.Enable(EnableCap.Texture2D);
            GL.BindTexture(TextureTarget.Texture2D, textureId);

            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.ColorArray);
            GL.EnableClientState(ArrayCap.NormalArray);
            GL.EnableClientState(ArrayCap.TextureCoordArray);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
            GL.VertexPointer(2, VertexPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _colorBufferId);
            GL.ColorPointer(4, ColorPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _normalBufferId);
            GL.NormalPointer(NormalPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ArrayBuffer, _textureBufferId);
            GL.TexCoordPointer(2, TexCoordPointerType.Float, 0, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBufferId);

            GL.DrawElements(BeginMode.Triangles, _indices.Length, DrawElementsType.UnsignedByte, 0);

            // Removing this has no effect
            GL.DisableClientState(ArrayCap.TextureCoordArray);
        }

        internal void UpdateQuadVertices(Int32 x, Int32 y, Int32 width, Int32 height)
        {
            _vertices[0].X = x;
            _vertices[0].Y = y;
            _vertices[1].X = x + width;
            _vertices[1].Y = y;
            _vertices[2].X = x;
            _vertices[2].Y = y + height;
            _vertices[3].X = x + width;
            _vertices[3].Y = y + height;

            GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBufferId);
            GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, (IntPtr) (_vertices.Length*Vector2.SizeInBytes),
                             _vertices);
            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
        }

        public Int32 LoadSimpleTexture()
        {
            Int32 textureObjectId;

            GL.GenTextures(1, out textureObjectId);
            GL.BindTexture(TextureTarget.Texture2D, textureObjectId);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
                            (Int32) TextureMinFilter.Linear);
            GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
                            (Int32)TextureMagFilter.Linear);

            var bitmap = new Bitmap("simple.png");
            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
                                              ImageLockMode.ReadOnly,
                                              System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
                          OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

            bitmap.UnlockBits(data);

            return textureObjectId;
        }
    }


    class Program
    {
        static void Main()
        {
            Int32 textureObjectId = 0;

            using (var gameWindow = new GameWindow(800, 600))
            {
                var renderer = new Renderer();
                gameWindow.Load += (s, e) =>
                                       {
                                           GL.ClearColor(Color.CornflowerBlue);
                                           GL.Enable(EnableCap.Blend);
                                           GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                                           GL.AlphaFunc(AlphaFunction.Greater, 1.0f);

                                           textureObjectId = renderer.LoadSimpleTexture();

                                       };
                gameWindow.Resize += (s, e) =>
                                         {
                                             GL.Viewport(0, 0, 800, 600);
                                             GL.MatrixMode(MatrixMode.Projection);
                                             GL.LoadIdentity();
                                             GL.Ortho(0, 800, 600, 0, -1, 1);
                                         };
                gameWindow.RenderFrame += (s, e) =>
                                              {
                                                  GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                                                  renderer.DrawQuad(0, 0, 128, 128);
                                                  renderer.DrawQuadTex(128, 0, 128, 128, textureObjectId);

                                                  gameWindow.SwapBuffers();
                                              };

                gameWindow.Run();
            }

        }
    }
}

更新

当我说首先调用的函数是显示形状的函数是不准确的时,实际上只有未纹理取代纹理(即,当存在 DrawQuad 时,只有未纹理可见)

4

1 回答 1

2

您发布的示例代码工作得很好。因此,我无法重现您描述的问题。从图片中可以明显看出,纹理和非纹理四边形都存在。然而,带纹理的四边形还与导致彩虹外观的颜色混合。要解决此问题,请禁用颜色指针或用白色填充颜色缓冲区。

如果您机器上的结果与我在下面发布的图片不匹配,则可能表明其他力量在起作用。一个可能的相关示例可能是视频卡(-驱动程序)的选择。

彩色和纹理四边形 彩色和纹理四边形

于 2013-01-29T10:32:15.453 回答