Qml 中用 Shader 实现圣诞树旋转灯
一、前言
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 实现圣诞树旋转灯相关推荐
- Unity中用shader graph制作一个简单的传送门效果
Unity中用shader graph制作一个简单的传送门效果 一.配置渲染管线 1.通过菜单"Asset" --> "Create" --> &q ...
- cocos2d-x3.2中用shader使图片背景透明
今天有人问我问题,说怎么实现背景虚化,换句话说,就是把某张图片的背景颜色(比如白色)给弄没了,不然贴在屏幕上有白色背景.下面是解决方法.用shader处理了像素,使黑色背景透明. Shader.h # ...
- Unity中用Shader实现镜子效果
做项目的时候要用到镜子,折腾了一下午,发现做镜子还是蛮快的,总结了一下网上的教程,大致有这么几种做法: 1.使用反射探针(Reflection Probe) 2.使用Render Texture 3. ...
- QML中用javascript 实现中文转换拼音
项目需要, 今天整理了一下.在QML调用javascrit将中文汉字转换成拼音. 感觉执行效率低. 下面是主要代码. 具体代码请参考QMLPinyin import "./pinyinjs/ ...
- QML中用C++多线程读取网页内容
在一开始我想在网页上爬取一些内容所以我想到了C++中的 QNetworkAccessManager 类 然后很自然的写了 QNetworkRequest request;request.setUrl( ...
- unity中用shader实现大海的特效
之前学过一个是做流水效果的 但是自我感觉效果不太好,波动太规律了,而且能看到上面的面像是由多个面组合成的,感觉有点假,不过功能是实现了. using UnityEngine; using System ...
- unity使ui面向镜头_pihqcam面向相机的软件ui
unity使ui面向镜头 Note: This article is part of a series of articles aimed at describing the complete pro ...
- Qt C++中 Map 和 List 转换到 QML 中使用
前言 C++中的 list 和 map 使用非常方便, 对应到 Qt 中的类型为 QList 和 QMap,在和 QML 交互的时候,可能也想用到这两个类型,或者说将 C++中的参数和 QML 中的参 ...
- JavaScript判断字符串中包含另一个字符串(QML 中使用)
前言 为啥会搞JavaScript呢,原因很简单,因为 QML 中用到了 JS 的语法,本来在 Qt 里面 QString 检查字符串是否包含一个子串是非常简单的事情,直接用contains()函数就 ...
最新文章
- jquery学习手记(9)事件基础知识
- wcf 远程终结点已终止该序列 可靠会话出错
- Oracle 系统改变号SCN详解
- 思维导图软件下载与安装 记录xmind安装过程
- 为什么说string是引用类型,但是又有值类型的特点呢?
- 机器学习与计算机视觉(计算机视觉的嵌入式平台)
- ajax-loader.gif不存在怎么解决_战神引擎不开门怎么解决?
- cobol学习之十数据库的增删改查模板
- Hibernate级联删除时:Cannot delete or update a parent row: a foreign key constraint fails异常...
- 收藏商品表设计_babycare商品价格及销售情况分析
- 一招让你的百度网盘免费不限速下载,每秒宽带满速下载
- MacOS连接VPN 提醒 “IPSec共享密钥”丢失。请验证您的设置并尝试重新连接。
- shadow acne(阴影失真)和peter panning(阴影悬浮)
- python中ndim是什么_使用Python中的ndim和shape属性获取darray数据的维度、长度、形状和其他参数,python,ndarray,等...
- 3-SII--Android的SD卡文件读写
- 【题目泛做】宝藏(期望)(类欧几里得)
- 离散数学与组合数学-04图论上
- Java第六课——画图板
- 吴军 阅读与写作50讲 发刊词 读后感
- 全新二改广告横幅在线生成源码 无数据库
热门文章
- 10、Horizon RDS远程桌面服务和应用程序池配置
- Ubtun16.04 配置baxter机器人
- 设备树下的 platform 驱动开发框架
- 57闭环步进电机57闭环步进电机方案57步进电机42 自己做的闭环驱动器,驱动器是全新的
- WindowManager
- linux 串口 设置rts,linux内核关于uart2配置为RTS引脚时,串口无法使用的问题
- 个人向前端知识“复健”
- 2021.10.12-13科研日志
- 2018/09/25渡课
- 以图搜图引擎 With Saprk