我有两个 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 时,只有未纹理可见)