4.纹理
vert
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aColor; layout (location = 2) in vec2 aTexCoord; out vec3 ourColor; out vec2 TexCoord; void main() { gl_Position = vec4(aPos, 1.0); ourColor = aColor; TexCoord = aTexCoord; }
frag
#version 330 core out vec4 FragColor; in vec3 ourColor; in vec2 TexCoord; uniform sampler2D texture1; uniform sampler2D texture2; void main() { //混合两个纹理,最后一个值是两者的比例,越大后者越明显 FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.8); }
.h
#pragma once #include <QOpenGLWidget> #include <QOpenGLExtraFunctions> #include <QOpenGLFunctions_3_3_Core> #include <QOpenGLShader> #include <QOpenGLShaderProgram> class CoreFunctionWidget : public QOpenGLWidget , protected /*QOpenGLExtraFunctions*/QOpenGLFunctions_3_3_Core { Q_OBJECT public: explicit CoreFunctionWidget(QWidget *parent = nullptr); ~CoreFunctionWidget(); protected: virtual void initializeGL(); virtual void resizeGL(int w, int h); virtual void paintGL(); private: QOpenGLShaderProgram shaderProgram; };
.cpp
#include "CoreFunctionWidget.h" #include <QDebug> #include <QTimer> //EBO是索引缓存对象 static GLuint VBO, VAO, EBO, texture1, texture2; CoreFunctionWidget::CoreFunctionWidget(QWidget *parent) : QOpenGLWidget(parent) { } CoreFunctionWidget::~CoreFunctionWidget() { glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); } void CoreFunctionWidget::initializeGL() { this->initializeOpenGLFunctions(); bool success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "textures.vert"); if (!success) { qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log(); return; } success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "textures.frag"); if (!success) { qDebug() << "shaderProgram addShaderFromSourceFile failed!" << shaderProgram.log(); return; } success = shaderProgram.link(); if (!success) { qDebug() << "shaderProgram link failed!" << shaderProgram.log(); } //VAO,VBO data float vertices[] = { // positions // colors // texture coords 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left }; //索引数组 unsigned int indices[] = { 0, 1, 2, // 第一个三角形 2, 3, 0// 第二个三角形 }; //生成三个对象 glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); //绑定VAO glBindVertexArray(VAO); //绑定VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //绑定EBO glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // 位置 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); glEnableVertexAttribArray(0);//开启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); //第一个纹理 glGenTextures(1, &texture1);//生成纹理 glBindTexture(GL_TEXTURE_2D, texture1);//绑定纹理,指定为2D // 设置纹理的环绕参数 //第二个参数需要我们指定设置的选项与应用的纹理轴。配置的是WRAP选项,并且指定S和T轴 //第三个参数 //GL_REPEAT 对纹理的默认行为。重复纹理图像 //GL_MIRRORED_REPEAT和GL_REPEAT一样,但每次重复图片是镜像放置的。 //GL_CLAMP_TO_EDGE 纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。 //GL_CLAMP_TO_BORDER 超出的坐标为用户指定的边缘颜色。 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // 设置纹理的过滤参数 //当进行放大(Magnify)和缩小(Minify)操作的时候可以设置纹理过滤的选项, //比如你可以在纹理被缩小的时候使用邻近过滤,被放大时使用线性过滤 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //载入jpg图片 QImage img1 = QImage("container.jpg").convertToFormat(QImage::Format_RGB888); if (!img1.isNull()) { /* GLenum target 指定活动纹理单元的目标纹理 GLint level 指定细节级别,0级表示基本图像,n级则表示Mipmap缩小n级之后的图像(缩小2^n) GLint internalformat 指定纹理内部格式 GLsizei width GLsizei height 指定纹理图像的宽高 GLint border 指定边框的宽度。必须为0 GLenum format 指定纹理数据的格式。必须匹配internalformat下面的符号值被接受:GL_ALPHA,GL_RGB,GL_RGBA,GL_LUMINANCE,和GL_LUMINANCE_ALPHA。 GLenum type 指定纹理数据的数据类型 const GLvoid * data 指定一个指向内存中图像数据的指针 */ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img1.width(), img1.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, img1.bits()); glGenerateMipmap(GL_TEXTURE_2D);//生成纹理 } // 第二个纹理 // --------- glGenTextures(1, &texture2); glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); QImage img2 = QImage("awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored(false,true);//通常需要这样翻转图片 if (!img2.isNull()) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img2.width(), img2.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, img2.bits()); glGenerateMipmap(GL_TEXTURE_2D);//生成纹理 } //启用着色器 shaderProgram.bind(); glUniform1i(shaderProgram.uniformLocation("texture1"), 0); glUniform1i(shaderProgram.uniformLocation("texture2"), 1); shaderProgram.release(); } void CoreFunctionWidget::resizeGL(int w, int h) { glViewport(0, 0, w, h); } void CoreFunctionWidget::paintGL() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); shaderProgram.bind(); { glActiveTexture(GL_TEXTURE0);//激活第一个纹理 glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1);//激活第二个纹理 (最多可以有32个纹理) glBindTexture(GL_TEXTURE_2D, texture2); //绑定VAO glBindVertexArray(VAO); //根据索引画 /* mode 指定要渲染的图元类型。 接受符号常量GL_POINTS,GL_LINE_STRIP,GL_LINE_LOOP,GL_LINES,GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN和GL_TRIANGLES。 count 指定要渲染的元素数。 type 指定indices中值的类型。 必须是GL_UNSIGNED_BYTE或GL_UNSIGNED_SHORT。 indices 指定指向存储索引的位置的指针。 */ glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } shaderProgram.release(); }


浙公网安备 33010602011771号