是自己来CSDN的第一篇文章。据说CSDN下载代码文件还要收积分,能看这个问题的多半是像我一样学生刚开始学,坚决不直接放文件收费!都是学生不容易!最近刚开始学openGL,想着怎么能画出旋转立方体,每个面可以有不同纹理,这里只用了三个照片,其中两张混合在一起(mix)作为一面(LearnopenGL课程中纹理单元那一节,忘记可以看看),此面在立方体中占了四个面,可以反色。另外一张是单独的作为一面,占有立方体剩下两面。如果想每个面都不一样,都是相同的道理,后面会讲。因为初学者,有一些可能理解有错,欢迎大家指出。学习是跟着Bilibili学的,所以代码很多部分是直接用了bilibili AXB老师的,在此感谢!(B站搜一个qtopengl就能搜出来)

大致效果图就是这样子(笑脸占了两面,剩下的反色的图片占了四面),

大致思路:

1.先自己写36*5个点,36是因为画6个面,每个面用6个点(两个三角形,这里没有用索引),然后5个点是前三个代表三角形的点坐标,后两个是纹理坐标。然后建立VAO,VBO,再分别绑定,刚开始想着用两个VAO和VBO,然后再用两个vertice数组,把笑脸的那两个放到一个vertice里,然后把那个混合照片的放另外一个数组里,但后来一想,不需要那样子做,用一个vertice完全可以,直接到时候VAO里的指针全部识别,在最后draw函数之前调用一下shederprogram程序就可以(这块刚开始学没懂的话后面也会详细讲)

2.创建两个着色器程序,一个就叫做shaderprogram,一个叫做shaderprogram1,后面简写S和S1。然后这俩加入源文件,再链接一下,就算激活着色器程序了。然后使用的时候,切记切记,一定要bind一下!!!我就是因为没有bind S1,然后莫名改了老半天,甚至怀疑之前学的是不是全部理解错了QAQ。这时候我们设一个QOpenGLtexture指针的值,把图片加载进去,并且用下mirror函数(镜像),不然Y坐标是负的,再bind一下,然后开始给着色器设置,使用setuniformvalue就行,默认的是0,然后比如混合图片多个纹理单元的话就再1 2 3.这里相当于给片段着色器里的采样器Sampler赋值,让他们区别开,跟你texture指针目前还没啥关系,后面绘画前才会开始真正的绑定。并且发现比较狗的一点是,如果你赋值时给textwall赋值,不小心写成了textwllll之类的,那边不会报错,而会将错就错的显示一张图片。然后开始用S1着色器程序,也是同理,S1因为是新的着色器程序,执行了新的着色器函数,所以setuniformvalue也是从0开始。

3.这一切完成后开始用3D空间知识了,这里不详细讲了,B站AXB老师和learnopenGL课程上讲的很明白,就是三个矩阵,model,view,projection。projection可以直接固定写法,view是观察矩阵,就是看你摄像机放在哪里了,然后记住view矩阵最后一个设置成负数,因为相当于从摄像机开始往前看,你的图像是Z轴负半轴,相当于正半轴从电脑屏幕指向你,而你看电脑屏幕时,以你为原点,电脑屏幕就是负半轴了。model矩阵的话,也很容易,进行translate和rotate操作,这里我们让他随时间改变,设个时间槽函数。

4.接下来万事俱备,只欠东风。开始调用,记住一定有三个bind,一个是VAO的bind,一个是着色器程序S的绑定,一个是着色器程序S1的绑定。相当于你刚开始用了VAO把数组vertice里传进去,不同的着色器程序绑定决定你去执行不同的代码。我们画的时候说清楚起始和结束点就可以了。比如bind vao后,我S绑定一下,然后QOpenGLtexture绑定某个值,让指针对象和之前赋值好的Sampler真正对应。这时我们开始绘画,你想画哪一部分的面就用drawarray函数,因为shader texture和vao不bind在一起的时候没啥关联,draw之前bind一下,就可以画你想要的效果了。

整体结构图

下面就是代码部分了

首先是头文件部分,第一个是我们新建的class,第二个是mianwindow.h

#ifndef AXBOPENGLWIDGET_H
#define AXBOPENGLWIDGET_H#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QTimer>
class AXBOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{Q_OBJECT
public:enum Shape{None,Rect,Circle,Triangle};explicit AXBOpenGLWidget(QWidget *parent = nullptr);~AXBOpenGLWidget();void drawShape(Shape shape);void setWirefame(bool wireframe);
protected:virtual void initializeGL();virtual void resizeGL(int w, int h);virtual void paintGL();void keyPressEvent(QKeyEvent *event);
signals:public slots:void on_timeout();
private:Shape m_shape;QOpenGLShaderProgram shaderProgram;QOpenGLShaderProgram shaderProgram1;QOpenGLTexture * textureWall;QOpenGLTexture * textureSmile;QOpenGLTexture * textureSmall;QTimer timer;
};#endif // AXBOPENGLWIDGET_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_actDrawRect_triggered();void on_actClear_triggered();void on_actWireframe_triggered();private:Ui::MainWindow *ui;
};#endif // MAINWINDOW_H

然后就是CPP了

#include "axbopenglwidget.h"
#include <QTime>
#include<math.h>
unsigned int VBO, VAO,EBO;
unsigned int VBO1, VAO1,EBO1;
float vertices[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,};QVector<QVector3D> cubePositions= {
QVector3D( 0.0f, 0.0f, 0.0f),
/*QVector3D( 2.0f, 5.0f, -15.0f),
QVector3D(-1.5f, -2.2f, -2.5f),
QVector3D(-3.8f, -2.0f, -12.3f),
QVector3D( 2.4f, -0.4f, -3.5f),
QVector3D(-1.7f, 3.0f, -7.5f),
QVector3D( 1.3f, -2.0f, -2.5f),
QVector3D( 1.5f, 2.0f, -2.5f),
QVector3D( 1.5f, 0.2f, -1.5f),
QVector3D(-1.3f, 1.0f, -1.5f)*/
};
float vertices1[]={-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};unsigned int indices[] = { // note that we start from 0!0, 1, 3, // first triangle1, 2, 3 // second triangle};
float ratio=0.5;
AXBOpenGLWidget::AXBOpenGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{setFocusPolicy(Qt::StrongFocus);connect(&timer,SIGNAL(timeout()),this,SLOT(on_timeout()));timer.start(100);
}AXBOpenGLWidget::~AXBOpenGLWidget()
{makeCurrent();glDeleteBuffers(1,&VBO);glDeleteBuffers(1,&EBO);glDeleteVertexArrays(1,&VAO);//glDeleteBuffers(1,&VBO1);//glDeleteBuffers(1,&EBO1);//glDeleteVertexArrays(1,&VAO1);doneCurrent();
}void AXBOpenGLWidget::drawShape(AXBOpenGLWidget::Shape shape)
{m_shape=shape;update();
}void AXBOpenGLWidget::setWirefame(bool wireframe)
{makeCurrent();if(wireframe)glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);elseglPolygonMode(GL_FRONT_AND_BACK,GL_FILL);update();doneCurrent();
}void AXBOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();bool success;shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/shapes.vert");shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/shapes.frag");success=shaderProgram.link();if(!success)qDebug()<<"ERR:"<<shaderProgram.log();shaderProgram1.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/shapes_1.vert");shaderProgram1.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/shapes_1.frag");success=shaderProgram1.link();if(!success)qDebug()<<"ERR:"<<shaderProgram1.log();textureWall=new QOpenGLTexture(QImage(":/images/images/wall.jpg").mirrored());textureSmile=new QOpenGLTexture(QImage(":/images/images/smile.jpeg").mirrored());
//bind以后然后赋值shaderProgram.bind();shaderProgram.setUniformValue("textureSmile",1);shaderProgram.setUniformValue("textureWall",0);QMatrix4x4 projection;projection.perspective(45,(float)width()/height(),0.1,100);shaderProgram.setUniformValue("projection", projection);glBindVertexArray(0);
//mirror是为了镜像,前面有讲textureSmall=new QOpenGLTexture(QImage(":/images/images/awesomeface.png").mirrored());shaderProgram1.bind();shaderProgram1.setUniformValue("textureSmall",0);shaderProgram1.setUniformValue("projection", projection);glBindVertexArray(0);}void AXBOpenGLWidget::resizeGL(int w, int h)
{//Q_UNUSED(w);Q_UNUSED(h);//glViewport(0, 0, w, h);
}void AXBOpenGLWidget::paintGL()
{QMatrix4x4 model;QMatrix4x4 view;QMatrix4x4 model1;QMatrix4x4 view1;unsigned int time=QTime::currentTime().msec();view.translate(0.0,0.0,-3);view1.translate(0.0,0.0,-3);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);shaderProgram.bind();shaderProgram.setUniformValue("ratio",ratio);shaderProgram.setUniformValue("view", view);model.setToIdentity();model.translate(cubePositions[0]);model.rotate(time, 1.0f, 1.0f, 1.0f);shaderProgram.setUniformValue("model", model);shaderProgram1.bind();shaderProgram1.setUniformValue("ratio",ratio);shaderProgram1.setUniformValue("view", view);shaderProgram1.setUniformValue("model", model);switch (m_shape) {case Rect:glBindVertexArray(VAO);shaderProgram1.bind();textureSmall->bind(0);glDrawArrays(GL_TRIANGLES,0,24);
//bind后可以知道执行哪一段着色器程序了,然后画出相应的点就可以了shaderProgram.bind();textureWall->bind(0);textureSmile->bind(1);glDrawArrays(GL_TRIANGLES,24,36);break;}
}
//这个是特效,按键盘上下键,两张混合图效果不同
#include <QKeyEvent>
void AXBOpenGLWidget::keyPressEvent(QKeyEvent *event)
{switch (event->key()) {case Qt::Key_Up:ratio+=0.1;break;case Qt::Key_Down:ratio-=0.1;break;default:break;}if(ratio>1) ratio=1;if(ratio<0) ratio=0;shaderProgram.bind();shaderProgram.setUniformValue("ratio",ratio);update();
}void AXBOpenGLWidget::on_timeout()
{update();
}

下面是mainwindow.cpp,main。cpp没变化,所以就不写了

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);setCentralWidget(ui->openGLWidget);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_actDrawRect_triggered()
{ui->openGLWidget->drawShape(AXBOpenGLWidget::Rect);
}void MainWindow::on_actClear_triggered()
{
//一些效果函数ui->openGLWidget->drawShape(AXBOpenGLWidget::None);
}void MainWindow::on_actWireframe_triggered()
{ui->openGLWidget->setWirefame(ui->actWireframe->isChecked());
}

这是ui图,注意三个地方,一个是窗口是openGLwidget,一个这个窗口要提升为头文件.h,让这个窗口和头文件联系起来(B站教程有),再就是底下的设置函数,这些B站AXB老师都有讲解,自己看视频很容易懂。

后面就是那四个着色器代码了

shapes.vert

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCord;
out vec2 TexCord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){gl_Position = projection*view*model*vec4(aPos.x, aPos.y, aPos.z, 1.0f);TexCord=aTexCord;
}

shapes.frag

#version 330 core
out vec4 FragColor;
out vec4 Color;
out vec4 textureColor;
in vec2 TexCord;
uniform sampler2D textureWall;
uniform sampler2D textureSmile;
uniform sampler2D textureSmall;
uniform float ratio;
void main(){textureColor = mix(texture(textureWall,TexCord),texture(textureSmile,TexCord),ratio);
//反色算法,就是1-rgb,最后加个alpha就行
FragColor=vec4(1.0-textureColor.r,1.0-textureColor.g,1.0-textureColor.b,1.0f);}

剩下的那俩,一个vert和上面的vert一样,剩下那个就正常显示,很easy,不反色

全部结束了,希望对你有帮助!

超详细讲解。QT+OpenGL画出不同纹理面立方体(部分面可反色)相关推荐

  1. Python的零基础超详细讲解(第十二天)-Python函数及使用

    基础篇往期文章: Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博 ...

  2. Python的零基础超详细讲解(第七天)-Python的数据的应用

    往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...

  3. python高级语法装饰器_Python高级编程——装饰器Decorator超详细讲解上

    Python高级编程--装饰器Decorator超详细讲解(上篇) 送你小心心记得关注我哦!! 进入正文 全文摘要 装饰器decorator,是python语言的重要特性,我们平时都会遇到,无论是面向 ...

  4. mybatis-plus超详细讲解

    (6条消息) mybatis-plus超详细讲解_zdsg45的博客-CSDN博客_mybatis-plushttps://blog.csdn.net/zdsg45/article/details/1 ...

  5. stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解)

    stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解) 首先看看效果吧 手机端发送一个数据在OLED屏幕上显示 其实蓝牙通信就是个蓝牙转串口的过程,手机 ...

  6. Java基础18-String类【String类的特点对象个数常用方法】【超详细讲解】

    Java基础-String类[超详细讲解] String类的特点 String在java.lang.String包中 1:特点 (1)String类型不能被继承,因为由final修饰 (2)Strin ...

  7. react的超详细讲解

    create-react-app 项目目录 在HTML中使用react 1 2 3基础 React的注意事项 模拟的React 和 render React组件 函数组件 类组件 React 的数据源 ...

  8. 生存曲线 p值 python_超详细讲解生信SCI中的生存曲线作图,不看后悔系列

    原标题:超详细讲解生信SCI中的生存曲线作图,不看后悔系列 在线及个性化精美Kaplan-Meier生存曲线的绘制 大家好,我是阿琛.俗话说,是骡子是马拉出来溜溜.在肿瘤研究中,一个基因的研究价值高不 ...

  9. Vue模仿todo超详细讲解(附源码)

    Vue模仿todo超详细讲解(附源码) 一.todo基本DOM结构 二.todo功能需求分析 1.新增任务 2.点击变成完成状态 3.点击删除 4.双击进入编辑以及修改保存 5.底部的状态筛选 6.l ...

  10. Python新手爬虫训练小项目《爬取彼岸图网》(超详细讲解版)

    Python新手爬虫训练小项目<爬取彼岸图网>(超详细讲解版) 这是我的第一篇文章,作为一名新手爬虫,这个算是我这几天来的努力成果,虽然代码寥寥几行但花费了大半天,新手上路还是不能只看视频 ...

最新文章

  1. Asp.net MVC突然变慢,缓存消失的一种原因
  2. 同事查询多行_从零学会SQL-简单查询
  3. 记一次Java动态代理实践
  4. 大四上学期的分数和分析感悟
  5. 详解:面向对象与面向过程的比较 类之间的关系:泛化、实现、依赖、关联、聚合、组合
  6. 面试让你手撕红黑树?30张图带你彻底理解红黑树~
  7. 计算机软件系统包括应用软件和什么,计算机软件系统包括什么
  8. JSR 299 建议草案第二版已提交
  9. 利用MapGis6.7 对 jpg图像文件进行图形校准
  10. zynq使用lwip远程更新flash
  11. 张健和他的Fcoin
  12. 那些黑科技感爆棚的可视化大屏,是怎么做出来的?模板直接套用
  13. java pdf添加透明水印_如何使用PDF编辑工具在PDF文件中添加透明水印
  14. 年后跳槽如何准备?(前端方向)
  15. 计算机在会计专业的作用论文开题报告,会计电算化对传统会计的影响开题报告.docx...
  16. 公司注册流程需要哪些步骤
  17. com.github.abel533.mapper插件使用报错,求助!!!
  18. 手把手教你搭建Spring Boot项目
  19. 18种各式各样的loading,纯html5+css3无图片
  20. firefox浏览器和火狐浏览器的驱动匹配问题,及对应的版本驱动下载(能解决99%问题)收藏

热门文章

  1. HDOJ 1001 Sum Problem
  2. 《Linux那些事儿之我是USB》我是U盘(14)冰冻三尺非一日之寒
  3. 昆明二级计算机考试报名时间2015,2015年国家司法考试昆明考区公告
  4. Ubuntu 更改默认浏览器
  5. Matlab加矩形窗程序,基于MATLAB结合矩形窗设计FIR滤波器
  6. 微信电子驾驶证怎么查询
  7. 【matplotlib】plot()kind参数表
  8. 消息队列返回错误:Resource temporarily unavailable
  9. IDEA 如何新建Source Folder
  10. 回溯法——最大团问题c