Qt OpenGL(04)Sierpinski 镂垫 3D 版

news2024/12/27 14:22:40

文章目录

  • 三维 Siepinski 镂垫
  • 相关代码
    • main.cpp
    • Help.hpp
    • Widget.h
    • Widget.cpp
    • 顶点着色器
    • 片元着色器
  • 总结

三维 Siepinski 镂垫

在这里插入图片描述

把前面的二维Sierpinski程序转换成一个生成三维Sierpinski镂垫的程序,也就是说要绘制的镂垫不再只是限制在一个平面里。我们可仿效对二维镂垫所使用的两种方法中的任何一种。 即用一个四面体代替初始的三角形

相关代码

  • std::vector 容器比较使用于OpenGL

  • 连续绑定 多个数组数据的使用方法

    • glBufferData (GL_ARRAY_BUFFER,points.size () * sizeof(QVector3D)* 2,NULL,GL_STATIC_DRAW);
    • glBufferSubData (GL_ARRAY_BUFFER, 0, points.size () * sizeof(QVector3D), points.data () );
    • glBufferSubData (GL_ARRAY_BUFFER, points.size () * sizeof(QVector3D), colors.size () * sizeof(QVector3D), colors.data () );
    • 每个面使用一种颜色
    color3 base_colors[4] = {
        color3(1.0,0.0,0.0),
        color3(0.0,1.0,0.0),
        color3(0.0,0.0,1.0),
        color3(1.0,1.0,0.0),
    };
    
  • 利用 pos 的 z 值加深显示,修改片元着色器

  • 添加 model 矩阵,并旋转动态显示

  • 屏幕缩放比例获取
    qApp->devicePixelRatio ();

  • Qt 的高分辨率设置,见main.cpp

main.cpp

#include "Widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute (Qt::AA_EnableHighDpiScaling);
    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec ();
}

Help.hpp

#ifndef HELPER_H
#define HELPER_H

#include <QVector3D>
typedef QVector3D point3;
typedef QVector3D color3;

extern std::vector<QVector3D> points;
extern std::vector<QVector3D> colors;

#include <QDebug>
#define qout if( 1 ) qDebug() << __FILE__ << __LINE__ << ": "

int colorindex;

color3 base_colors[4] = {
    color3(1.0,0.0,0.0),
    color3(0.0,1.0,0.0),
    color3(0.0,0.0,1.0),
    color3(1.0,1.0,0.0),
};

void triangle(point3 a, point3 b, point3 c) {
    static int i = 0;
    colors.emplace_back (base_colors[colorindex]);
    points.emplace_back (a);
    ++i;

    colors.emplace_back (base_colors[colorindex]);
    points.emplace_back (b);
    ++i;

    colors.emplace_back (base_colors[colorindex]);
    points.emplace_back (c);
    ++i;

}

void tetra(point3 a, point3 b, point3 c,point3 d) {
    colorindex = 0;
    triangle(a,b,c);
    colorindex = 1;
    triangle(a,c,d);
    colorindex = 2;
    triangle(a,b,d);
    colorindex = 3;
    triangle(b,d,c);
}

void divide_tetra(point3 a, point3 b, point3 c,point3 d, int m) {
    if(m > 0 )
    {
        point3  mid[6];
        mid[0] = (a+b)/2.0;
        mid[1] = (a+c)/2.0;
        mid[2] = (a+d)/2.0;
        mid[3] = (b+c)/2.0;
        mid[4] = (c+d)/2.0;
        mid[5] = (b+d)/2.0;

        // 通过细分生成4个四面体
        divide_tetra (a,      mid[0], mid[1], mid[2], m-1);
        divide_tetra (mid[0],      b, mid[3], mid[5], m-1);
        divide_tetra (mid[1], mid[3],      c, mid[4], m-1);
        divide_tetra (mid[2], mid[5], mid[4],      d, m-1);
    }
    else
        tetra (a,b,c,d);
}

#endif // WIDGET_H

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>


class Widget : public QOpenGLWidget,QOpenGLFunctions_3_3_Core
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    // QOpenGLWidget interface
protected:
    virtual void initializeGL() override;
    virtual void paintGL() override;
    virtual void resizeGL(int w, int h) override;

private:
    unsigned int VAO,VBO;
    QOpenGLShaderProgram shaderProgram;

    // void (Widget::* p)();

    int min,max;

    double ratio;	// 存放屏幕的缩放比例,Qt 5.15
};
#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include "Helper.hpp"
#include "qcoreapplication.h"
#include "qelapsedtimer.h"
#include "qmatrix4x4.h"
#include "qvector3d.h"
#include <QThread>
#include <QDebug>
#include <QRandomGenerator>
#include <algorithm>
#include <vector>
#include <QApplication>

#define qRandom   QRandomGenerator::global ()
#define qout if( 0 ) qDebug() << __FILE__ << __LINE__ << ": "

constexpr int NumTimesToSubdivide = 3;

// std::vector 是内存连续的容器,比较适合opengl 的数据绑定
std::vector<QVector3D> points;
std::vector<QVector3D> colors;

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    setWindowTitle ("04_Siepinski_Recursion_3D");
    resize (300,300);

    int NumTriangles = std::pow(4,NumTimesToSubdivide+1) * 3;
    qout << NumTriangles;

    points.reserve (NumTriangles);	// 最后优化才添加的代码
    colors.reserve (NumTriangles);  // 最后优化才添加的代码
    qout << points.size () << points.capacity ();  // 大小 和 容量

    p = &Widget::update;

    ratio = qApp->devicePixelRatio ();

}

Widget::~Widget()
{
    makeCurrent ();
    glDeleteBuffers (1,&VBO);
    glDeleteVertexArrays (1,&VAO);
    doneCurrent ();
}

void Widget::initializeGL()
{
    initializeOpenGLFunctions ();

    const char *version =(const char *) glGetString (GL_VERSION);
    qout << QString(version);

    QVector3D vertices[4] = {
//        QVector3D(-1.0,-1.0,-1.0),
//        QVector3D( 1.0,-1.0,-1.0),
//        QVector3D( 0.0, 1.0,-1.0),
//        QVector3D( 0.0, 0.0, 1.0)

        QVector3D( 0.0f, 0.0f, -1.0f),
        QVector3D( 0.0f, 0.942809f, 0.333333f),
        QVector3D(-0.816497f, -0.471405f, 0.333333f),
        QVector3D( 0.816497f, -0.471405f, 0.333333f)
    };
    // 参考 https://blog.csdn.net/zhanxi1992/article/details/105771685中的数据
    QElapsedTimer timer;
    timer.start ();

    // 对初始的4面体进行细分
    divide_tetra (vertices[0],vertices[1],vertices[2],vertices[3],NumTimesToSubdivide);

    qout << timer.elapsed ();

    glGenBuffers (1,&VBO);
    glBindBuffer (GL_ARRAY_BUFFER,VBO);
    glBufferData (GL_ARRAY_BUFFER,points.size () * sizeof(QVector3D)* 2,NULL,GL_STATIC_DRAW);

    glBufferSubData (GL_ARRAY_BUFFER,
                     0,
                     points.size () * sizeof(QVector3D),
                     points.data () );

    glBufferSubData (GL_ARRAY_BUFFER,
                     points.size () * sizeof(QVector3D),
                     colors.size () * sizeof(QVector3D),
                     colors.data () );

    glGenVertexArrays (1,&VAO);
    glBindVertexArray(VAO);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D), (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(QVector3D), (void*)(points.size () * sizeof(QVector3D)));
    glEnableVertexAttribArray(1);

    shaderProgram.addShaderFromSourceFile (QOpenGLShader::Vertex,  ":/shader.vert");
    shaderProgram.addShaderFromSourceFile (QOpenGLShader::Fragment,":/shader.frag");
    shaderProgram.link ();

    glBindBuffer (GL_ARRAY_BUFFER,0);

//    glPolygonMode (GL_FRONT_AND_BACK,GL_LINE);

    // 使能 深度测试
    glEnable(GL_DEPTH_TEST);
}

int count = 3;
QMatrix4x4 model;
void Widget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);   // 设置背景色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    shaderProgram.bind ();
    shaderProgram.setUniformValue ("u_color",1.0f, 0.5f, 0.2f, 1.0f);
    model.rotate ( 2, 1.0, 1.0, 1.0);
    glViewport ((max-min)/2 ,0,min,min);
    shaderProgram.setUniformValue ("model",model);
    glBindVertexArray(VAO);


    // 绘制三角形扇形
    glDrawArrays (GL_TRIANGLES,0,(int)points.size ());

    QThread::currentThread ()->msleep (50);
//    (this->*p)();
    update ();
}

void Widget::resizeGL(int w, int h)
{
    qout << "resizeGL";
    min = std::min (w,h) * ratio;
    max = std::max (w,h) * ratio;
}

顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
out  vec4 Color;

uniform mat4 model;

void main()
{
   gl_Position = model * vec4(aPos.x, aPos.y, aPos.z, 1.0);
   Color = vec4( aColor.xyz * (1-gl_Position.z)/2,1.0);
};

片元着色器

#version 330 core
out vec4 FragColor;
uniform vec4 u_color;
in vec4 Color;

void main()
{
//    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
    FragColor = Color;
}

总结

  • std::vector 使用十分方便
  • glViewport ((max-min)/2 ,0,min,min); 要在渲染过程调用才有用处【奇怪】
  • Qt 的高分辨率设置,windows屏幕的缩放比率获取,见widget.cpp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138122.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么? @ConditionalOnMissingBean 你没设置value?

序 这两天再看 公司 之前写的组件的代码&#xff0c;不看不知道&#xff0c;一看吓一跳。。。。这里就说其中一个 不知道你在写组件中的 Bean 加载的时候 怎么写&#xff1f; 方法一 直接META-INF/spring.factories 写 org.springframework.boot.autoconfigure.EnableAuto…

消息队列应用与原理剖析

什么是消息队列 消息队列&#xff1a;在消息的传输过程中保存消息的容器&#xff0c;生产者和消费者不直接通讯&#xff0c;依靠队列保证消息的可靠性&#xff0c;避免了系统间的相互影响。系统间的数据流通道 应用场景 异步处理&#xff1a;用户注册后&#xff0c;需要发注…

linux C--管道

这里写自定义目录标题基本概念管道特征编写模型有名管道模型示例demowrite.cread.c结果记录笔记1无名管道基本概念 进程间存在天然的壁垒,进程间通信(Interperocess Communication,IPC)是指二个或者多个进程之间进行数据交换的过程 管道特征 管道是进程间通讯的一种常用方法…

Tomcat安装及使用

1.下载 Tomcat官网 选择系统 2.解压 解压到没有中文路径的文件夹中,解压路径会在配置环境变量时用到 3.配置环境变量 在电脑点击鼠标右键->点击属性>点击高级系统设置->点击环境变量->新建系统变量 1.新建系统变量 变量名为CATALINA_HOME&#xff0c;变…

【unity3D】DoTween动画插件(下)

&#x1f497; 未来的游戏开发程序媛&#xff0c;现在的努力学习菜鸡 &#x1f4a6;本专栏是我关于游戏开发的学习笔记 &#x1f236;本篇是unity的DoTween动画插件可视化编辑 DoTween动画插件&#xff08;可视化编辑&#xff09;DOTween AnimationDoTween Path路径编辑器Scene…

【Linux】Linux编辑器—vim使用

目录1.vim的基本概念2.vim基本操作3.vim命令模式命令集4.vim末行模式命令集5.简单vim配置6.使用sudo提权为什么要学习vim&#xff1f; “在 Linux 系统中一切都是文件&#xff0c;而配置一个服务就是在修改其配置文件的参数”。 而且在日常工作中大家也肯定免不了要编写文档&am…

学习C语言笔记:浮点类型float、double和long double

浮点类型能表示包括小数在内更大范围的数。浮点数的表示类似于科学计数法&#xff08;即用小数乘以10的幂来表示数字&#xff09;。该记数系统常用于表示非常大或非常小的数。 float C语言规定&#xff0c;float类型必须至少能表示6位有效数字&#xff0c;且取值范围至少是~…

【阶段二】Python数据分析Pandas工具使用03篇:数据预处理:多表合并与连接

本篇的思维导图: 数据预处理:多表合并与连接 将表结构相同(即变量个数和变量类型均相同)的多张表纵向合并到一张长表中,或者将多张表的变量水平扩展到一张宽表中。 需要注意的是,对于多表之间的纵向合并,则必须确保多表的列数和数据类型一致;对于多表之间的水平扩展,…

电子邮件帐户受损报告,请查收!

我们收到有关恶意访问 Ambire Wallet 电子邮件帐户的报告。 所有这些账户都是用在 CoinMarketCap/Ledger/其他黑客事件中被破坏的电子邮件地址注册的。 我们的内部调查显示&#xff0c;Ambire 的内部系统没有被泄露。我们调查的所有受影响的账户都是因为他们的电子邮件被泄露&…

FOFA(一): FOFA入门

文章目录一、FOFA是什么二、Fafo的使用1. 用户注册2. 一般使用3. 高级用法三、界面解释一般检索结果ip聚合:统计:以ip为单位的资产数据统计:四、API参考一、FOFA是什么 部署在互联网上的网络设备资产信息搜索引擎。旨在尽可能多的对全球IT设备资产进行信息收集、 漏洞扫描&…

java知识图谱+Java语言特点+常用dos命令+Java程序总结

java知识图谱高级语言Java语言特点注释单行注释 //多行注释/* */作用&#xff1a;1.对程序的编写进行解释说明&#xff0c;增强可读性2.调试所写代码单行/多行注释不参与编译&#xff1b;多行注释不可嵌套使用文档注释&#xff08;Java特有&#xff09;/** */注释内容可被JDK提…

系统治理 体系规划新型数据安全防护体系

声明 本文是学习2022中国工业数据勒索形势分析报告. 下载地址 http://github5.com/view/55028而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 工业数据勒索应急响应事件攻击者分析 应急响应事件攻击者分析以2022年1-9月所有工业数据勒索应急数据为支撑…

Hadoop HDFS

Hadoop HDFS分布式文件系统分布式文件系统的优点HDFS(Hadoop分布式文件系统)应用常见hdfs集群存储机制元数据管理namespace分布式文件系统 既然我们要学习hdfs那就不能不提分布式文件系统 文件系统是一种存储和组织数据的方法&#xff0c;实现了数据的存储、分级组织、访问和…

Linux DNS 解析与配置 nslookup使用 与 /etc/resolv.conf文件的配置

Linux DNS 解析与配置 序 当我接收到一批新的服务器时&#xff0c;尝试连接外网&#xff0c;比如访问百度的首页&#xff1a; curl www.baidu.com发现报错&#xff0c;不能解析正确的主机名。这个其实就是主机在解析主机名时没能正确发现对应的主机的 ip。当我们使用类似于域…

华为交换机配置笔记

交换机(Switch)是一种用于电信号转发的网络设备,它可以为接入交换机的任意两个网络节点提供独享的电信号通路,最常见的交换机是以太网交换机,其他常见的还有电话语音交换机、光纤交换机等,交换机是集线器的升级替代产品,理论上讲交换机就是按照通信两端传输信息的需求,将需要的…

ONES 入选极客公园「2022 中国创新力量 50 」榜单

极客公园调研发现&#xff0c;2022 年是企业服务的「双杀」转折点&#xff1a;内部造血的难度升级&#xff0c;外部输血的可能性降低。为了表彰逆流而上的企服公司&#xff0c;极客公园对其给予了重点鼓励和点评。其中&#xff0c;企业级研发管理平台 ONES 入选了极客公园 2022…

vue js游戏,抗疫小游戏,抗疫的汤圆,仅以此小游戏献给所有为抗击疫情做出贡献的人

vue js游戏&#xff0c;抗疫小游戏&#xff0c;抗疫的汤圆&#xff0c;仅以此小游戏献给所有为抗击疫情做出贡献的人 完整代码下载地址&#xff1a;vue js游戏&#xff0c;抗疫小游戏&#xff0c;抗疫的汤圆 建议在pc上使用Chrome浏览器进行访问&#xff0c;如果只能手机玩&a…

还不快收藏起来!何恺明全网最全论文合集

原创/文 BFT机器人 人物简介 何恺明&#xff0c;Facebook AI Research (FAIR) 的一名科学家&#xff0c;研究领域包括计算机视觉和深度学习&#xff0c;并且在计算机视觉和深度学习方面发表了众多极具影响力的论文。 他发表的论文中&#xff0c;有关深度残差网络 (ResNets) 的…

当下的零售新进化,同以往的电商时代还是有着很多区别的

一场数字化的浪潮&#xff0c;正在各行各业深刻上演着。在零售领域&#xff0c;亦不例外。以往&#xff0c;提及零售&#xff0c;我们更多地想到的是&#xff0c;各式各样的电商平台&#xff0c;我们看到的是&#xff0c;各式各样的电商模式&#xff1b;现在&#xff0c;提及零…

学习一下如何使用python实现一个超级卡哇伊的五角星吧

Hello呀朋友们~ 今天实在想不出要写啥了&#xff0c;但是前两天有朋友让我写一个五角星&#xff0c;这个好说呀&#xff0c;必须安排的妥妥当当的&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 在这里我就不多说了&#xff0c;这个也挺简单的&#xff0c;那…