一、前言

        2022年圣诞节到来啦,很高兴这次我们又能一起度过~

这次给大家带来一个简单漂亮圣诞树灯。

当然了,本篇文章主要是讲解一下如何在 Qml 中使用 GLSL 来实现自己的特效。

至于代码嘛,我比较喜欢在 Shadertoy 上寻找,那里有很多超级炫酷的着色器实现的特效,并且可以很轻松的集成到 Qml 中。


二、纯 GLSL 实现的圣诞树旋转灯

首先,想要在 Qml 中使用 GLSL,我们需要借助 ShaderEffect。

ShaderEffect 类型将自定义顶点和片段(像素)着色器应用于矩形。它允许在 QML 场景中添加阴影、模糊、着色和页面卷曲等效果。
注意:根据使用的 Qt Quick Scenegraph 后端,可能不支持 ShaderEffect 类型。例如,使用软件后端,则根本不会渲染效果。

ShaderEffect 有两个重要属性:

vertexShader: 此属性保存顶点着色器源码字符串 ( 实际上也可以是文件 )。

fragmentShader: 此属性保存片元着色器源码字符串 ( 实际上也可以是文件 )。

我这里就比较简单了,直接将着色器代码文件传入即可:

import QtQuick 2.15
import QtQuick.Window 2.15Window {id: rootwidth: 1280height: 900visible: truetitle: qsTr("Christmas tree lights")ShaderEffect {anchors.fill: parentvertexShader: "file:./glsl/christmas_tree_lights.vert"fragmentShader: "file:./glsl/christmas_tree_lights.frag"property vector3d iResolution: Qt.vector3d(root.width, root.height, 0)property real iTime: 0Text {text: "Time: " + parent.iTime.toFixed(2)color: "white"}Timer {running: truerepeat: trueinterval: 10onTriggered: parent.iTime += 0.01;}}
}

当然,还要向着色器中传入一些 uniform 变量,直接在 Qml 中声明即可,Qt 会自动帮我们传入。

着色器的代码来自 Shadertoy:https://www.shadertoy.com

顶点着色器很简单,直接传递变量,计算顶点即可:

#version 450uniform mat4 qt_Matrix;
in vec4 qt_Vertex;
out vec4 fragCoord;void main() {fragCoord = qt_Vertex;gl_Position = qt_Matrix * qt_Vertex;
}

然后是片元着色器( 比较复杂 ) :

#version 450in vec4 fragCoord;uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float iTime;      // shader playback time (in seconds)const float pi = 3.1415927;
const float dotsnbt = 90.0; // Number of dots for the tree
const float dotsnbs = 20.0; // Number of dots for the star (per circle)vec3 hsv2rgb (vec3 hsv) { // from HSV to RGB color vectorhsv.yz = clamp (hsv.yz, 0.0, 1.0);return hsv.z * (1.0 + 0.63 * hsv.y * (cos (2.0 * 3.14159 * (hsv.x + vec3 (0.0, 2.0 / 3.0, 1.0 / 3.0))) - 1.0));
}void mainImage(out vec4 fragColor, in vec2 fragCoord)
{float time = iTime;float mx = max(iResolution.x, iResolution.y);vec2 scrs = iResolution.xy / mx;vec2 uv = vec2(fragCoord.x, iResolution.y - fragCoord.y) / mx;//vec2 m = vec2(mouse.x / scrs.x, mouse.y * (scrs.y / scrs.x));vec2 pos = vec2(0.0);               // Position of the dotsvec3 col = vec3(0.0);               // Color of the dotsfloat intensitys = 1.0 / 4000.0;    // Light intensity for the starfloat intensityt = 1.0 / 2000.0;    // Light intensity for the treefloat scale = 0.2;                  // Size of the star/*** Star ***/for(float i = 0.0 ; i < dotsnbs; i++){pos = vec2(cos(time * 0.2) / 20.0 * cos(2.0 * pi * i / dotsnbs),0.15 * sin(2.0 * pi * i / dotsnbs)) * scale;pos += vec2(scrs.x / 2.0, scrs.y * 0.11);col += hsv2rgb(vec3(i / dotsnbs, distance(uv, pos) * (1.0 / intensitys), intensitys / distance(uv, pos)));pos = vec2(0.12 * cos(2.0 * pi * i / dotsnbs + time * 0.2),0.08 * sin(2.0 * pi * i / dotsnbs)) * scale;pos += vec2(scrs.x / 2.0, scrs.y * 0.11);col += hsv2rgb(vec3(1.0 - i / dotsnbs, distance(uv, pos) * (1.0 / intensitys), intensitys / distance(uv, pos)));pos = vec2(0.12 * cos(2.0 * pi * i / dotsnbs + time * 0.2),-0.08 * sin(2.0 * pi * i / dotsnbs)) * scale;pos += vec2(scrs.x / 2.0, scrs.y * 0.11);col += hsv2rgb(vec3(i / dotsnbs, distance(uv, pos) * (1.0 / intensitys), intensitys / distance(uv, pos)));}/*** Tree ***/float angle = dotsnbt * 1.8; // Angle of the conefor(float i = 0.0 ; i < dotsnbt ; i++){pos = vec2(scrs.x / 2.0 + sin(i / 2.0 - time * 0.2) / (3.0 / (i + 1.0) * angle),scrs.y * ((i) / dotsnbt + 0.21) * 0.80);col += hsv2rgb(vec3(1.5 * i / dotsnbt + fract(time / 4.0), distance(uv, pos) * (1.0 / intensityt), intensityt / distance(uv, pos)));}fragColor = vec4( col, 1.0 );
}void main(void)
{mainImage(gl_FragColor, vec2(fragCoord.x, iResolution.y - fragCoord.y));
}

三、效果展示

_(:3 」∠)_  动图质量不太行,大家凑合看。


四、结语

另外,要提一点:

在Qt 5中,效果以GLSL(OpenGL着色语言)源代码的形式提供,通常作为字符串嵌入QML中。从Qt 5.8开始,可以引用本地文件或Qt资源系统中的文件。
在Qt 6中,Qt Quick支持图形API,如Vulkan、Metal和Direct3D 11。因此,使用GLSL源字符串不再可行。相反,新的着色器管道基于将Vulkan兼容的GLSL代码编译成SPIR-V,然后收集反射信息并翻译成其他着色语言,如HLSL、金属着色语言和各种GLSL版本。生成的资产被打包到一个单独的包中,通常存储在扩展名为.qsb的文件中。此过程最迟在应用程序构建时离线完成。在运行时,场景图和底层图形抽象使用这些.qsb文件。因此,ShaderEffect需要Qt 6中的文件(本地或qrc)引用来代替内联着色器代码。
例如,vertexShader和fragmentShader属性是Qt 6中的URL,其工作方式与Image.source非常相似。然而,ShaderEffect仅支持文件和qrc方案。也可以省略文件方案,以便以方便的方式指定相对路径。这样的路径是相对于组件(.qml文件)位置解析的。

因此,在 Qt 6 中,我们可以使用更加广泛的 qsb,这样只需要写一种着色器即可支持所有后端。

不过关于 qsb 具体如何使用,我后面会写一下相关的博客~


五、源码下载

Github的:

https://github.com/mengps/ShadertoyExampleshttps://github.com/mengps/ShadertoyExamples        CSDN的:

https://download.csdn.net/download/u011283226/87342581https://download.csdn.net/download/u011283226/87342581

Qml 中用 Shader 实现圣诞树旋转灯相关推荐

  1. Unity中用shader graph制作一个简单的传送门效果

    Unity中用shader graph制作一个简单的传送门效果 一.配置渲染管线 1.通过菜单"Asset" --> "Create" --> &q ...

  2. cocos2d-x3.2中用shader使图片背景透明

    今天有人问我问题,说怎么实现背景虚化,换句话说,就是把某张图片的背景颜色(比如白色)给弄没了,不然贴在屏幕上有白色背景.下面是解决方法.用shader处理了像素,使黑色背景透明. Shader.h # ...

  3. Unity中用Shader实现镜子效果

    做项目的时候要用到镜子,折腾了一下午,发现做镜子还是蛮快的,总结了一下网上的教程,大致有这么几种做法: 1.使用反射探针(Reflection Probe) 2.使用Render Texture 3. ...

  4. QML中用javascript 实现中文转换拼音

    项目需要, 今天整理了一下.在QML调用javascrit将中文汉字转换成拼音. 感觉执行效率低. 下面是主要代码. 具体代码请参考QMLPinyin import "./pinyinjs/ ...

  5. QML中用C++多线程读取网页内容

    在一开始我想在网页上爬取一些内容所以我想到了C++中的 QNetworkAccessManager 类 然后很自然的写了 QNetworkRequest request;request.setUrl( ...

  6. unity中用shader实现大海的特效

    之前学过一个是做流水效果的 但是自我感觉效果不太好,波动太规律了,而且能看到上面的面像是由多个面组合成的,感觉有点假,不过功能是实现了. using UnityEngine; using System ...

  7. unity使ui面向镜头_pihqcam面向相机的软件ui

    unity使ui面向镜头 Note: This article is part of a series of articles aimed at describing the complete pro ...

  8. Qt C++中 Map 和 List 转换到 QML 中使用

    前言 C++中的 list 和 map 使用非常方便, 对应到 Qt 中的类型为 QList 和 QMap,在和 QML 交互的时候,可能也想用到这两个类型,或者说将 C++中的参数和 QML 中的参 ...

  9. JavaScript判断字符串中包含另一个字符串(QML 中使用)

    前言 为啥会搞JavaScript呢,原因很简单,因为 QML 中用到了 JS 的语法,本来在 Qt 里面 QString 检查字符串是否包含一个子串是非常简单的事情,直接用contains()函数就 ...

最新文章

  1. jquery学习手记(9)事件基础知识
  2. wcf 远程终结点已终止该序列 可靠会话出错
  3. Oracle 系统改变号SCN详解
  4. 思维导图软件下载与安装 记录xmind安装过程
  5. 为什么说string是引用类型,但是又有值类型的特点呢?
  6. 机器学习与计算机视觉(计算机视觉的嵌入式平台)
  7. ajax-loader.gif不存在怎么解决_战神引擎不开门怎么解决?
  8. cobol学习之十数据库的增删改查模板
  9. Hibernate级联删除时:Cannot delete or update a parent row: a foreign key constraint fails异常...
  10. 收藏商品表设计_babycare商品价格及销售情况分析
  11. 一招让你的百度网盘免费不限速下载,每秒宽带满速下载
  12. MacOS连接VPN 提醒 “IPSec共享密钥”丢失。请验证您的设置并尝试重新连接。
  13. shadow acne(阴影失真)和peter panning(阴影悬浮)
  14. python中ndim是什么_使用Python中的ndim和shape属性获取darray数据的维度、长度、形状和其他参数,python,ndarray,等...
  15. 3-SII--Android的SD卡文件读写
  16. 【题目泛做】宝藏(期望)(类欧几里得)
  17. 离散数学与组合数学-04图论上
  18. Java第六课——画图板
  19. 吴军 阅读与写作50讲 发刊词 读后感
  20. 全新二改广告横幅在线生成源码 无数据库

热门文章

  1. 10、Horizon RDS远程桌面服务和应用程序池配置
  2. Ubtun16.04 配置baxter机器人
  3. 设备树下的 platform 驱动开发框架
  4. 57闭环步进电机57闭环步进电机方案57步进电机42 自己做的闭环驱动器,驱动器是全新的
  5. WindowManager
  6. linux 串口 设置rts,linux内核关于uart2配置为RTS引脚时,串口无法使用的问题
  7. 个人向前端知识“复健”
  8. 2021.10.12-13科研日志
  9. 2018/09/25渡课
  10. 以图搜图引擎 With Saprk