纹理单元
OpenGL保证至少有16个纹理单元,即可以激活从 GL_TEXTURE0 (默认是激活的)到 GL_TEXTRUE15。它们都是按顺序定义的。
激活和绑定纹理单元
OpenGL原生:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
Qt封装:
QOpenGLTexture * texture = new QOpenGLTexture(QImage(":/images/images/wall.jpg").mirrored());
shaderProgram.bind(0);//激活和绑定第0个纹理单元
纹理单元示例
//顶点着色器
#version 450 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aColor;
layout(location = 2) in vec2 aTexCord;
out vec3 ourColor;
out vec2 TexCord;
void main()
{
gl_Position = vec4(aPos, 1.0f);
ourColor=aColor;
TexCord=aTexCord;
}
//片段着色器
#version 450 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCord;
uniform sampler2D textureWall;
uniform sampler2D textureSmile;
void main()
{
FragColor = mix(texture(textureWall,TexCord),
texture(textureSmile,TexCord),0.5);
}
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLShaderProgram>
class Widget : public QOpenGLWidget,QOpenGLFunctions_4_5_Core
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
virtual void initializeGL();
virtual void paintGL();
private:
class QOpenGLTexture * textureWall;
QOpenGLTexture * textureSmile;
QOpenGLShaderProgram shaderProgram;
};
#endif // WIDGET_H
#include "widget.h"
#include <QOpenGLShaderProgram>
#include <QTimer>
#include <QTime>
#include <QOpenGLTexture>
unsigned int VBO, VAO,EBO;
float vertices[] =
{
//位置 颜色 纹理坐标
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
unsigned int indices[] =
{
0, 1, 3,
1, 2, 3
};
Widget::Widget(QWidget *parent) : QOpenGLWidget(parent)
{
}
Widget::~Widget()
{
makeCurrent();
glDeleteBuffers(1,&VBO);
glDeleteBuffers(1,&EBO);
glDeleteVertexArrays(1,&VAO);
doneCurrent();
}
void Widget::initializeGL()
{
initializeOpenGLFunctions();
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shapes.vert");
shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shapes.frag");
if(!shaderProgram.link())
qDebug()<<"着色器程序编译错误信息:"<<shaderProgram.log();
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
textureWall = new QOpenGLTexture(QImage(":/image/wall.jpg").mirrored());
textureSmile = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored());
shaderProgram.bind();
shaderProgram.setUniformValue("textureWall",0);//纹理单元0
shaderProgram.setUniformValue("textureSmile",1);//纹理单元1
glBindVertexArray(0);
}
void Widget::paintGL()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.bind();
glBindVertexArray(VAO);
textureWall->bind(0);
textureSmile->bind(1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
}
纹理环绕方式
纹理过滤
- GL_NEAREST:使用纹理中坐标最接近的一个像素的颜色作为需要绘制的像素颜色。
- GL_LINEAR:使用纹理中坐标最接近的若干个颜色,通过加权平均算法得到需要绘制的像素颜色。