Неправильное отображение текстуры при использовании QGLBuffer

Я сделал базовый пример OpenGL 2.1\ES для предполагаемой целевой платформы, используя библиотеку Qt 4.7.1 для Windows. Целью является какой-то Linux с максимальной доступной версией Qt 4.8, без glm или подобных библиотек. Встроенный графический процессор поддерживает только 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 и то, что они соответствуют правильным вершинам, но похоже, что порядок координат текстур неверен. Где здесь ошибка?

Для справки: исходный код

Это моя первая попытка использования гибкого пайплайна, так что я мог бы сделать там что-нибудь глупое.


person Swift - Friday Pie    schedule 24.07.2014    source источник


Ответы (1)


Вы настраиваете свой буфер координат текстуры как индексный буфер:

m_texBuffer = new QGLBuffer(QGLBuffer::IndexBuffer );

Поскольку он содержит данные атрибутов вершины, он должен быть создан как:

m_texBuffer = new QGLBuffer(QGLBuffer::VertexBuffer);
person Reto Koradi    schedule 25.07.2014
comment
головные столы повторно Спасибо, сработало. По иронии судьбы, имелось в виду, что изначально это была вершина. Это тот самый случай, когда автор не видит свою опечатку - я не догадался, что изменение типа буфера просто исказит текстуру - я ожидал черный куб или нечто столь же нефункциональное. - person Swift - Friday Pie; 25.07.2014