麻烦纹理 VBO
Posted
技术标签:
【中文标题】麻烦纹理 VBO【英文标题】:Trouble Texturing VBO 【发布时间】:2014-09-20 19:30:44 【问题描述】:似乎我在我的游戏中纹理化 VBO 时遇到了一些问题。 VBO 本身似乎渲染得很好,我什至可以相应地切换面。然而,当我尝试添加纹理时,一切看起来都是歪斜的,有些纹理甚至出现在错误的面上。当我使用 VAO 时一切正常,所以我现在不知道为什么纹理突然不起作用。
这是一张图片:
这里是相关的数据:
private static uint frontFaceHandle;
private static uint backFaceHandle;
private static uint leftFaceHandle;
private static uint rightFaceHandle;
private static uint topFaceHandle;
private static uint bottomFaceHandle;
private static uint indexBufferId;
private static uint colorBufferId;
private static uint texCoordBufferId;
private static float[] textureCoordData =
0, 1,
1, 1,
1, 0,
0, 0,
;
private static ushort[] indices =
0, 1, 3,
0, 3, 2
;
private static float[] colorData =
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
;
private static float[] frontFaceVert =
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f
;
private static float[] backFaceVert =
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
;
private static float[] leftFaceVert =
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
;
private static float[] rightFaceVert =
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
;
private static float[] topFaceVert =
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
;
private static float[] bottomFaceVert =
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
;
我上传数据的方式:
static Voxel()
/**
* Front Face
*/
GL.GenBuffers( 1 , out frontFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( frontFaceVert.Length * sizeof( float ) ) ,
frontFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Back Face
*/
GL.GenBuffers( 1 , out backFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , backFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( backFaceVert.Length * sizeof( float ) ) ,
backFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Left Face
*/
GL.GenBuffers( 1 , out leftFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , leftFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( leftFaceVert.Length * sizeof( float ) ) ,
leftFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Right Face
*/
GL.GenBuffers( 1 , out rightFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , rightFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( rightFaceVert.Length * sizeof( float ) ) ,
rightFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Top Face
*/
GL.GenBuffers( 1 , out topFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , topFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( topFaceVert.Length * sizeof( float ) ) ,
topFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Bottom Face
*/
GL.GenBuffers( 1 , out bottomFaceHandle );
GL.BindBuffer( BufferTarget.ArrayBuffer , bottomFaceHandle );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )( bottomFaceVert.Length * sizeof( float ) ) ,
bottomFaceVert ,
BufferUsageHint.StaticDraw );
/**
* Texture Buffer
*/
GL.GenBuffers( 1 , out texCoordBufferId );
GL.BindBuffer( BufferTarget.ArrayBuffer , texCoordBufferId );
GL.BufferData( BufferTarget.ArrayBuffer , ( IntPtr )( textureCoordData.Length * sizeof( float ) ) , textureCoordData , BufferUsageHint.StaticDraw );
/**
* Index Buffer
*/
GL.GenBuffers( 1 , out indexBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.BufferData(
BufferTarget.ElementArrayBuffer ,
( IntPtr )( indices.Length * sizeof( ushort ) ) ,
indices ,
BufferUsageHint.StaticDraw );
/**
* Color buffer (This Remains unused for now
*/
GL.GenBuffers( 1 , out colorBufferId );
GL.BindBuffer( BufferTarget.ArrayBuffer , colorBufferId );
GL.BufferData(
BufferTarget.ArrayBuffer ,
( IntPtr )colorData.Length ,
colorData ,
BufferUsageHint.StaticDraw );
以及我绘制立方体的方式(每个面都是一个单独的 vbo):
public void Render( FirstPersonCameraWidget gameCamera )
GL.Translate( Location.X , Location.Y , Location.Z );
GL.Enable( EnableCap.Texture2D );
GL.EnableClientState( ArrayCap.VertexArray );
GL.EnableClientState( ArrayCap.TextureCoordArray );
if( ShowFrontFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.FrontFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
if( ShowBackFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , backFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.BackFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
if( ShowLeftFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , leftFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.LeftFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
if( ShowRightFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , rightFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.RightFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
if( ShowTopFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , topFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.TopFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
if( ShowBottomFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , bottomFaceHandle );
GL.BindBuffer( BufferTarget.TextureBuffer , texCoordBufferId );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.BottomFace.GetID() );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
GL.Translate( -Location.X , -Location.Y , -Location.Z );
希望有人能发现我做错了什么。
更新:根据@Andom M. Coleman 的建议,我已经修复了代码并且它有效,但是立方体仍然略微倾斜。
【问题讨论】:
【参考方案1】:您为纹理坐标数组和位置数组使用不同的 VBO,对吗?这些东西没有离散的绑定位置,您的代码实际上应该如下所示:
if( ShowFrontFace )
GL.BindBuffer( BufferTarget.ArrayBuffer , frontFaceHandle );
GL.VertexPointer( 3 , VertexPointerType.Float , 0 , IntPtr.Zero );
// ArrayBuffer!
GL.BindBuffer( BufferTarget.ArrayBuffer , texCoordBufferId );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
GL.BindTexture( TextureTarget.Texture2D , TextureAtlas.FrontFace.GetID() );
GL.BindBuffer( BufferTarget.ElementArrayBuffer , indexBufferId );
GL.DrawElements( PrimitiveType.Triangles , 6 , DrawElementsType.UnsignedShort , IntPtr.Zero );
注意:BufferTarget.TextureBuffer
实际上是针对缓冲区对象(Texture Buffer Objects)的完全不同用途。
对于顶点缓冲区,您将始终将它们绑定到 BufferTarget.ArrayBuffer
,然后下一个 gl___CoordPointer (...)
调用将与当前绑定的内容相关。
在您的原始代码中,由于 BufferTarget.ArrayBuffer
仅设置一次,因此您的纹理坐标指针实际上来自与您的顶点位置相同的数据集。这显然不是你想要的行为。
其实,如果你想花哨,你可以把纹理指针的规范拉出分支,因为它是不变的。每次绘制立方体时,只需执行以下一次:
GL.BindBuffer ( BufferTarget.ArrayBuffer , texCoordBufferId );
GL.TexCoordPointer( 2 , TexCoordPointerType.Float , 0 , IntPtr.Zero );
【讨论】:
我肯定会这样做,但是,您知道为什么我的纹理仍然略微倾斜吗?是我的纹理坐标吗? 是的,从你的顶点位置设置的方式来看,我认为你的坐标实际上应该是:0,0 0,1 1,0 1,1。 那些坐标将所有东西都翻转到它的一边,但至少现在我知道它是纹理坐标。感谢您的帮助;现在接受作为答案。 正确的纹理坐标是:private static float[] textureCoordData = 0, 1, 1, 1, 0, 0, 1, 0 ;以上是关于麻烦纹理 VBO的主要内容,如果未能解决你的问题,请参考以下文章