终于我们可以把图片贴到我们的图形上了
纹理坐标
当我们把图片贴到我们的正方形上,需要指定四个角的对应关系,这就是纹理坐标,通常,我们希望图片左下角对应正方形左下角,图片右上角对应正方形右上角,如果对应错了,图片就会上下颠倒,左右颠倒
把原来顶点颜色数组改为,顶点纹理坐标数组
//VAO数据,顶点与颜色
VertexData1 vcs[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector2D(0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector2D(1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector2D(1.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector2D(0.0f, 1.0f)}, //4
}
索引
//索引
GLuint indices[] = { // 起始于0!
0, 1, 2, 3,// face 1
}
常用步骤
//1 使用glGenBuffers函数生成一个缓冲ID
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
//2 绑定vao
glBindVertexArray(VAO);
//3 使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER缓冲类型上
glBindBuffer(GL_ARRAY_BUFFER, VBO); //(绑定和解绑的顺序很重要,勿更改)
//4 把用户定的义数据复制到当前绑定缓冲的函数
glBufferData(GL_ARRAY_BUFFER, sizeof(vcs), vcs, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//5 链接顶点属性
//indx: 属性名
//size: 顶点大小
//type: 数据类型
//normalized:数据被标准化
//stride: 步长
//ptr: 数据在缓冲中起始位置的偏移量
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData1), (GLvoid*)0);
glVertexAttribPointer(m_texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData1), (GLvoid*)(sizeof(QVector3D)));
//(GLvoid*)(sizeof(QVector3D)
//6 解绑缓存着色器(绑定和解绑的顺序很重要,勿更改)
glBindBuffer(GL_ARRAY_BUFFER, 0);
//7 解绑VAO
glBindVertexArray(0);
创建纹理
用一张图片生成纹理,我们使用QOpenGLTexture来很方便的实现
//使用图片的垂直镜像来创建纹理
m_texture = new QOpenGLTexture(QImage(":/cube1.png").mirrored());
//设置纹理过滤器的滤波方式
//当图片缩小的比原始纹理小的时候 滤波方式为 mip层之间使用线性插值和使用线性过滤
m_texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
//当图片放大的比原始纹理大的时候 滤波方式为 mip基层上使用线性过滤
m_texture->setMagnificationFilter(QOpenGLTexture::Linear);
//设置图片格式
m_texture->setFormat(QOpenGLTexture::RGBFormat);
//纹理绑定
m_texture->bind();
//使用纹理单元
m_program->setUniformValue("texture", 0);
绘制
//纹理绑定
m_texture->bind();
//1 绑定vao
glBindVertexArray(VAO);
//2 开启顶点属性
glEnableVertexAttribArray(0);
//颜色值
glEnableVertexAttribArray(2);
//3 绘制四边形
//24个索引值
// glDrawArrays(GL_QUADS, 0, 24);
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (GLvoid*)0);
//4 停用对应的顶点属性数组
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(0);
//5 解绑VAO
glBindVertexArray(0);
//纹理释放
m_texture->release();
注意
- 启用2D纹理映射,否则显示白色
//启用2D纹理映射
glEnable(GL_TEXTURE_2D);
- 启用纹理对应的属性,否则显示白色
glEnableVertexAttribArray(2);
六面纹理-单一
思考了一下,每个面对应一个图片,如果用索引,只有8个点,死活对应不上,只好放弃索引,重新使用24个点
struct VertexData
{
QVector3D position;
QVector3D color;
QVector3D texture;
};
VertexData vc[] = {
//正面
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(0.0f, 0.0f)}, //1
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f), QVector2D(1.0f, 0.0f)}, //2
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f), QVector2D(1.0f, 1.0f)}, //3
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f), QVector2D(0.0f, 1.0f)}, //4
//右面
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f), QVector2D(0.0f, 0.0f)}, //2
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f), QVector2D(1.0f, 0.0f)}, //5
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f), QVector2D(1.0f, 1.0f)}, //6
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f), QVector2D(0.0f, 1.0f)}, //3
//左面
{QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f), QVector2D(0.0f, 0.0f)}, //8
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(1.0f, 0.0f)}, //1
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f), QVector2D(1.0f, 1.0f)}, //4
{QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f), QVector2D(0.0f, 1.0f)}, //7
//背面
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f), QVector2D(0.0f, 0.0f)}, //5
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f), QVector2D(1.0f, 0.0f)}, //8
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f), QVector2D(1.0f, 1.0f)}, //7
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f), QVector2D(0.0f, 1.0f)}, //6
//顶面
{QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f), QVector2D(0.0f, 0.0f)}, //4
{QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f), QVector2D(1.0f, 0.0f)}, //3
{QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f), QVector2D(1.0f, 1.0f)}, //6
{QVector3D(-0.5f, 1.0f, -0.5f), QVector3D(1.0f, 0.6f, 0.0f), QVector2D(0.0f, 1.0f)}, //7
//底面
{QVector3D(-0.5f, 0.0f, -0.5f), QVector3D(1.0f, 0.0f, 1.0f), QVector2D(0.0f, 0.0f)}, //8
{QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f), QVector2D(1.0f, 0.0f)}, //5
{QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f), QVector2D(1.0f, 1.0f)}, //2
{QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f), QVector2D(0.0f, 1.0f)}, //1
};
纹理坐标链接时候注意要跳过两个QVector3D大小
//5 链接顶点属性
//indx: 属性名
//size: 顶点大小
//type: 数据类型
//normalized:数据被标准化
//stride: 步长
//ptr: 数据在缓冲中起始位置的偏移量
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0); //(GLvoid*)0
glVertexAttribPointer(m_texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)(sizeof(QVector3D)*2));
使用 glDrawArrays(GL_QUADS, 0, 24);绘制
下次我们做个骰子出来
先说一个坑
同样的代码拿回家就不好用,研究发现,绘制时候没启用颜色顶点,所以一直是黑屏
//颜色值
glEnableVertexAttribArray(1);
骰子的六面
要贴6次纹理,所以用指针数组, 管理全部纹理
声明数组
//纹理对象 数组
QVector<QOpenGLTexture *> m_vTexture;
创建数组
for(int i=0; i<6; i++)
{
//使用图片的垂直镜像来创建纹理
QString path = QString(":/cube%1.png").arg(QString::number(i+1));
QOpenGLTexture *_texture = new QOpenGLTexture(QImage(path).mirrored());
//设置纹理过滤器的滤波方式
//当图片缩小的比原始纹理小的时候 滤波方式为 mip层之间使用线性插值和使用线性过滤
_texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
//当图片放大的比原始纹理大的时候 滤波方式为 mip基层上使用线性过滤
_texture->setMagnificationFilter(QOpenGLTexture::Linear);
m_vTexture.append(_texture);
}
绘制注意问题
开启顶点属性
//2 开启顶点属性
glEnableVertexAttribArray(0);
//颜色值
glEnableVertexAttribArray(1);
//纹理
glEnableVertexAttribArray(2);
6个面要依次绘制一遍,绘制的起点也要依次往后移动
//纹理绑定
for(int i=0; i<6; i++)
{
m_vTexture.at(i)->bind();
//3 绘制四边形
//24个索引值
glDrawArrays(GL_QUADS, i*4, 4);
// glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, (GLvoid*)0);
m_vTexture.at(i)->release();
}
停用顶点属性
//4 停用对应的顶点属性数组
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
同时显示颜色和纹理
gl_FragColor = col*texture2D(texture, v_texcoord);