1. 程式人生 > >Qt Opengl-QOpenGLTexture-3D

Qt Opengl-QOpenGLTexture-3D

  • 關於紋理,可以理解為影象資料,在2D紋理中,就是將一張影象蓋在模型上,模型中空;至於3D紋理,就可以解釋為若干張影象,在通俗講就是多維陣列,多層切片的實體。
  • 紋理座標,x軸水平向右,y軸垂直向上,z軸朝向螢幕內,可以看作是3維座標下的第一象限的單元格。
  • 紋理貼圖,可以理解為,斷續的頂點資料和多維資料建立一個map(這是我們常規理解,當然也可以是紋理到頂點的map)

一個矩形上貼一個圖片,如下:

/*     頂點           紋理  
 *    x     y   z   x  y  z
 *  -0.5, -0.5, 0,  0, 0, 0
 *   0.5, -0.5, 0,  1, 0, 0
 *   0.5,  0.5, 0,  1, 1, 0,
 *  -0.5,  0.5, 0,  0, 1, 0,
*/

下面說說3D紋理的理解

void CubeRender::initTexture()
{
    // 圖片的寬,高,圖片的張數
    int width;
    int height;    
    int count
    // QImage imageList 載入
    
    // 將imageList資料拷貝到buffer,image的格式Format_RGBA8888
    uchar *buffer = getImageData(imageList);
    
    // 建立3D紋理
    m_texture = new QOpenGLTexture(QOpenGLTexture::Target3D);
    m_texture->create();
    m_texture->setSize(width, height, count);
    m_texture->setFormat(QOpenGLTexture::RGBA8_UNorm);
    m_texture->allocateStorage();
    // 紋理資料填充
    m_texture->setData(QOpenGLTexture::RGBA,QOpenGLTexture::UInt8,buffer);
    // 過濾處理
    m_texture->setMinMagFilters(QOpenGLTexture::Nearest,QOpenGLTexture::Nearest);
    // 3軸環繞
    m_texture->setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::ClampToEdge);
    m_texture->setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::ClampToEdge);
    m_texture->setWrapMode(QOpenGLTexture::DirectionR,QOpenGLTexture::ClampToEdge);
    delete [] buffer;
    buffer = nullptr;
}

這樣,我們就做好一個3D紋理,使用時

// 頂點資料(頂點座標,紋理座標)
void CubeRender::render(QMatrix4x4 vpmat){
    m_buffer.bind();
    m_indexBuffer.bind();
    m_shaderPro->bind();
    
    // 使用一個紋理,因為我們只建立了一個
    m_shaderPro->setUniformValue("qt_Texture0", 0);
    // 頂點座標
    m_shaderPro->enableAttributeArray(0);
    m_shaderPro->setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(QVector3D));
    // 紋理座標
    m_shaderPro->enableAttributeArray(1);
    m_shaderPro->setAttributeBuffer(1, GL_FLOAT, sizeof(QVector3D)*vertexVec.length(), 3,         sizeof(QVector3D));
    
    // 矩陣
    QMatrix4x4 modelMat;
    modelMat.setToIdentity();
    m_shaderPro->setUniformValue("qt_ModelViewProjectionMatrix",vpmat * modelMat);

    // 3D紋理繫結
    m_texture->bind();

    // 繪製 因為我們使用了索引buffer即EBO
    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_SHORT, nullptr);

    // 釋放
    m_texture->release();
    m_shaderPro->release();
    m_indexBuffer.release();
    m_buffer.release();
}

著色器部分,紋理座標通過屬性由程式傳給頂點著色器,進而中傳給片元著色器

/***頂點著色器***/
attribute vec4 qt_Vertex;
// 紋理座標
attribute vec3 qt_MultiTexCoord0;
uniform mat4 qt_ModelViewProjectionMatrix;
// 中傳紋理座標
varying vec3 qt_TexCoord0;

void main(void)
{
    gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
    
    qt_TexCoord0 = qt_MultiTexCoord0;
}

/***片元著色器***/
uniform sampler3D qt_Texture0;
varying vec3 qt_TexCoord0;

void main(void)
{
    gl_FragColor = texture3D(qt_Texture0, qt_TexCoord0);
}
  • QOpenGLBuffer,buffer的型別,VBO/EBO;buffer的用法,static/Dynamic