使用QG Buffer时纹理映射不正确

时间:2014-07-24 12:38:21

标签: opengl textures glsl shader qt4.7

我在Windows上使用Qt 4.7.1库为假定的目标平台制作了基本的OpenGL 2.1 \ ES示例。 Target是某种Linux,Qt 4.8最大可用,没有glm或类似的库。嵌入式GPU仅支持ES 1.0或OpenGL 2.1。例子是"经典"纹理多维数据集,你可能会在各种OpenGL示例中遇到..但是这些示例使用对OpenGL函数的直接调用,因为缺乏正确的标题和glew而无法在开发和目标平台上使用。开发平台是Windows 7。

几何

 static const int vertexDataCount = 6 * 4 * 4;

 static const float vertexData[vertexDataCount] = {
 // Left face
-0.5f, -0.5f, -0.5f, 1.0f,//0
-0.5f, -0.5f,  0.5f, 1.0f,//1
-0.5f,  0.5f,  0.5f, 1.0f,//2
-0.5f,  0.5f, -0.5f, 1.0f,//3

// Top face
-0.5f, 0.5f, -0.5f, 1.0f, //4
-0.5f, 0.5f,  0.5f, 1.0f, //5
 0.5f, 0.5f,  0.5f, 1.0f, //6
 0.5f, 0.5f, -0.5f, 1.0f, //7

// Right face
0.5f,  0.5f, -0.5f, 1.0f,//8
0.5f,  0.5f,  0.5f, 1.0f,//9
0.5f, -0.5f,  0.5f, 1.0f,//10
0.5f, -0.5f, -0.5f, 1.0f,//11

// Bottom face
 0.5f, -0.5f, -0.5f, 1.0f,//12
 0.5f, -0.5f,  0.5f, 1.0f,//13
-0.5f, -0.5f,  0.5f, 1.0f,//14
-0.5f, -0.5f, -0.5f, 1.0f,//15

// Front face
 0.5f, -0.5f, 0.5f, 1.0f,//16/
 0.5f,  0.5f, 0.5f, 1.0f,//17
-0.5f,  0.5f, 0.5f, 1.0f,//18
-0.5f, -0.5f, 0.5f, 1.0f,//19

// Back face
 0.5f,  0.5f, -0.5f, 1.0f,//20
 0.5f, -0.5f, -0.5f, 1.0f,//21
-0.5f, -0.5f, -0.5f, 1.0f,//22
-0.5f,  0.5f, -0.5f, 1.0f //23
};

// Normal vectors
static const int normalDataCount = 6 * 4 * 3;

static const float normalData[normalDataCount] = {
// Left face
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,

// Top face
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,

// Right face
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,

// Bottom face
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,

// Front face
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,

// Back face
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f
};


// Texure coords
static const int textureCoordDataCount = 6 * 4 * 2;
static const float textureCoordData[textureCoordDataCount] = {
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,

1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,

1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,

1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,

1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f,

1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
0.0f, 0.0f
};


// Indices
//
// 3 indices per triangle
// 2 triangles per face
// 6 faces
static const int indexDataCount = 6 * 3 * 2;

static const unsigned int indexData[indexDataCount] = {
0,  1,  2,  0,  2,  3,  // Left face
4,  5,  6,  4,  6,  7,  // Top face
8,  9,  10, 8,  10, 11, // Right face
12, 14, 15, 12, 13, 14, // Bottom face
16, 17, 18, 16, 18, 19, // Front face
20, 22, 23, 20, 21, 22  // Back face
};

这就是我加载纹理的方法

glEnable(GL_TEXTURE_2D);

m_texture = bindTexture(QImage("cube.png"));

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

if(m_shaderProgram)
    m_shaderProgram->setUniformValue("texture", 0); // texture unit 0, assuming that we used

顶点着色器

#version 120

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

attribute vec4 vertex;
attribute vec3 normal;
attribute vec2 texturecoord;

varying vec3 fragmentNormal;
varying vec2 outtexture;

void main( void )
{
    // Transform the normal vector
    fragmentNormal = ( modelViewMatrix * vec4( normal, 0.0 ) ).xyz;

    // Calculate the clip-space coordinates
    gl_Position = projectionMatrix * modelViewMatrix * vertex;
    outtexture = texturecoord;
}

片段着色器

#version 120

// in
uniform sampler2D texture;

varying vec2 outtexture;
varying vec3 fragmentNormal;
// out
// gl_FragColor

void main( void )
{
    // Calculate intensity as max of 0 and dot product of the
    // fragmentNormal and the eye position (0,0,1).
    float intensity;

    intensity = max( dot( fragmentNormal, vec3( 0.0, 0.0, 1.0 ) ), 0.15 );
    gl_FragColor = intensity * texture2D(texture,outtexture); // vec4( 1.0, 0.0, 0.0, 1.0 );
}

我以这种方式绑定缓冲区(prepareBufferObject是我从Qt示例中获取的小片段函数):

// Prepare the vertex, normal and index buffers
m_vertexBuffer = new QGLBuffer(QGLBuffer::VertexBuffer );
if ( !prepareBufferObject( m_vertexBuffer, QGLBuffer::StaticDraw, vertexData, sizeof(vertexData) ) )
    return;

m_normalBuffer = new QGLBuffer(QGLBuffer::VertexBuffer );
if ( !prepareBufferObject( m_normalBuffer, QGLBuffer::StaticDraw, normalData, sizeof(normalData) ) )
    return;

m_texBuffer = new QGLBuffer(QGLBuffer::IndexBuffer );
if ( !prepareBufferObject( m_texBuffer, QGLBuffer::StaticDraw, textureCoordData, sizeof(textureCoordData) ) )
    return;

m_indexBuffer = new QGLBuffer(QGLBuffer::IndexBuffer );
if ( !prepareBufferObject( m_indexBuffer, QGLBuffer::StaticDraw, indexData, sizeof(indexData) ) )
    return;


loadShaders("vertexshader120.glsl", "fragshader120.glsl");

// Enable the "vertex" attribute to bind it to our vertex buffer
m_vertexBuffer->bind();
m_shaderProgram->setAttributeBuffer( "vertex", GL_FLOAT, 0, 4 ); //xyzw
m_shaderProgram->enableAttributeArray( "vertex" );

// Enable the "normal" attribute to bind it to our texture coords buffer
m_normalBuffer->bind();
m_shaderProgram->setAttributeBuffer( "normal", GL_FLOAT, 0, 3 ); //xyz
m_shaderProgram->enableAttributeArray( "normal" );

m_texBuffer->bind();
m_shaderProgram->setAttributeBuffer( "texturecoord", GL_FLOAT, 0, 2 ); //uv
m_shaderProgram->enableAttributeArray( "texturecoord" );

// Bind the index buffer ready for drawing
m_indexBuffer->bind();

最后,paintGL方法

void GWidget::paintGL()
{
    QMatrix4x4 model;
    model.setToIdentity();
    model.rotate(m_rotation);

    QMatrix4x4 mv = m_view * model;

    // MVP = projection * view * model
    // uploading MVP into shader (may add code to check if MVP was update since last redraw)
    m_shaderProgram->setUniformValue("modelViewMatrix",mv);
    m_shaderProgram->setUniformValue("projectionMatrix",m_projection);

    // set up to render the scene
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Draw stuff
    glDrawElements( GL_TRIANGLES,       // Type of primitive to draw
                indexDataCount,     // The number of indices in our index buffer we wish to draw
                GL_UNSIGNED_INT,    // The element type of the index buffer
                0 );                // Offset from the start of our index buffer of where to begin
}

除了纹理在开发和目标平台上看起来未对齐和倾斜之外,一切都有效。我检查了UV并且它们对应于正确的顶点 - 但它看起来像纹理坐标的顺序是错误的。这里的错误在哪里?

供参考:source code

这是我第一次尝试使用灵活的管道,所以我可以做一些愚蠢的事情。

1 个答案:

答案 0 :(得分:1)

您正在将纹理坐标缓冲区设置为索引缓冲区:

m_texBuffer = new QGLBuffer(QGLBuffer::IndexBuffer );

由于它包含顶点属性数据,因此应将其创建为:

m_texBuffer = new QGLBuffer(QGLBuffer::VertexBuffer);