热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Qt6QMLBook/图形效果/片段着色器

FragmentShaders片段着色器Thefragmentshaderiscalledforeverypixeltoberendered.Inthischapter,wew

Fragment Shaders
片段着色器

The fragment shader is called for every pixel to be rendered. In this chapter, we will develop a small red lens which will increase the red color channel value of the source.

对要渲染的每个像素调用片段着色器。在本章中,我们将开发一个小的红色透镜,它将增加光源的红色通道值。

Setting up the scene


设置场景

First, we set up our scene, with a grid centered in the field and our source image be displayed.

首先,我们设置场景,以场为中心的网格显示源图像。

import QtQuickRectangle {width: 480; height: 240color: '#1e1e1e'Grid {anchors.centerIn: parentspacing: 20rows: 2; columns: 4Image {id: sourceImagewidth: 80; height: widthsource: '../../assets/tulips.jpg'}}
}

A red shader


红色着色器

Next, we will add a shader, which displays a red rectangle by providing for each fragment a red color value.

接下来,我们将添加一个着色器,通过为每个片段提供一个红色值来显示一个红色矩形。

#version 440layout(location=0) in vec2 qt_TexCoord0;layout(location=0) out vec4 fragColor;layout(std140, binding=0) uniform buf {mat4 qt_Matrix;float qt_Opacity;
} ubuf;layout(binding=1) uniform sampler2D source;void main() {fragColor = vec4(1.0, 0.0, 0.0, 1.0) * ubuf.qt_Opacity;
}

In the fragment shader we simply assign a vec4(1.0, 0.0, 0.0, 1.0), representing the color red with full opacity (alpha=1.0), to the fragColor for each fragment, turning each pixel to a solid red.

在片段着色器中,我们只需为每个片段的fragColor指定一个vec4(1.0、0.0、0.0、1.0),用完全不透明度(alpha=1.0)表示红色,将每个像素变成纯红色。

A red shader with texture


带有纹理的红色着色器

Now we want to apply the red color to each texture pixel. For this, we need the texture back in the vertex shader. As we don’t do anything else in the vertex shader the default vertex shader is enough for us. We just need to provide a compatible fragment shader.

现在我们要将红色应用于每个纹理像素。为此,我们需要在顶点着色器中恢复纹理。由于我们不在顶点着色器中执行任何其他操作,因此默认的顶点着色器对我们来说就足够了。我们只需要提供一个兼容的片段着色器。

#version 440layout(location=0) in vec2 qt_TexCoord0;layout(location=0) out vec4 fragColor;layout(std140, binding=0) uniform buf {mat4 qt_Matrix;float qt_Opacity;
} ubuf;layout(binding=1) uniform sampler2D source;void main() {fragColor = texture(source, qt_TexCoord0) * vec4(1.0, 0.0, 0.0, 1.0) * ubuf.qt_Opacity;
}

The full shader contains now back our image source as variant property and we have left out the vertex shader, which if not specified is the default vertex shader.

完整着色器现在包含了图像源的variant属性,我们省略了顶点着色器,如果没有指定,它就是默认的顶点着色器。

In the fragment shader, we pick the texture fragment texture(source, qt_TexCoord0) and apply the red color to it.

在片段着色器中,我们拾取纹理片段texture(source, qt_TexCoord0)并对其应用红色。

The red channel property


红色通道属性

It’s not really nice to hard code the red channel value, so we would like to control the value from the QML side. For this we add a redChannel property to our shader effect and also declare a float redChannel inside the uniform buffer of the fragment shader. That is all that we need to do to make a value from the QML side available to the shader code.

对红色通道值进行硬编码不是很好,所以我们希望从QML端控制该值。为此,我们在着色器效果中添加了一个redChannel属性,并在片段着色器的统一缓冲区内声明了一个float redChannel。这就是我们需要做的一切,以使着色器代码可以使用QML端的值。

TIP

Notice that the redChannel must come after the implicit qt_Matrix and qt_Opacity in the uniform buffer, ubuf. The order of the parameters after the qt_ parameters is up to you, but qt_Matrix and qt_Opacity must come first and in that order.

请注意,redChannel必须位于uniform缓冲区ubuf中的隐式qt_Matrixqt_Opacity之后。qt_ parameters之后的参数顺序由您决定,但qt_Matrixqt_Opacity必须排在第一位,并且按此顺序排列。

#version 440layout(location=0) in vec2 qt_TexCoord0;layout(location=0) out vec4 fragColor;layout(std140, binding=0) uniform buf {mat4 qt_Matrix;float qt_Opacity;float redChannel;
} ubuf;layout(binding=1) uniform sampler2D source;void main() {fragColor = texture(source, qt_TexCoord0) * vec4(ubuf.redChannel, 1.0, 1.0, 1.0) * ubuf.qt_Opacity;
}

To make the lens really a lens, we change the vec4 color to be vec4(redChannel, 1.0, 1.0, 1.0) so that the other colors are multiplied by 1.0 and only the red portion is multiplied by our redChannel variable.

为了使镜头真正成为镜头,我们将vec4颜色更改为vec4(redChannel, 1.0, 1.0, 1.0),以便其他颜色乘以1.0,只有红色部分乘以我们的redChannel变量。

The red channel animated


红色通道动画

As the redChannel property is just a normal property it can also be animated as all properties in QML. So we can use QML properties to animate values on the GPU to influence our shaders. How cool is that!

由于redChannel属性只是一个普通属性,因此它也可以作为QML中的所有属性设置动画。因此,我们可以使用QML属性在GPU上设置值的动画,以影响着色器。多酷啊!

ShaderEffect {id: effect4width: 80; height: widthproperty variant source: sourceImageproperty real redChannel: 0.3visible: root.step>3NumberAnimation on redChannel {from: 0.0; to: 1.0; loops: Animation.Infinite; duration: 4000}fragmentShader: "red3.frag.qsb"
}

Here the final result.

 这里是最终结果。

The shader effect on the 2nd row is animated from 0.0 to 1.0 with a duration of 4 seconds. So the image goes from no red information (0.0 red) over to a normal image (1.0 red).

第二行的着色器效果在0.0到1.0之间设置动画,持续时间为4秒。因此,图像从没有红色信息(0.0红色)变为正常图像(1.0红色)。

Baking


生成

Again, we need to bake the shaders. The following commands from the command line does that:

同样,我们需要烘焙着色器。命令行中的以下命令可执行此操作:

qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -o red1.frag.qsb red1.frag
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -o red2.frag.qsb red2.frag
qsb --glsl 100es,120,150 --hlsl 50 --msl 12 -o red3.frag.qsb red3.frag

示例源码下载 


推荐阅读
  • td{border:1pxsolid#808080;}参考:和FMX相关的类(表)TFmxObjectIFreeNotification ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • 本文详细介绍了`android.os.Binder.getCallingPid()`方法的功能和应用场景,并提供了多个实际的代码示例。通过这些示例,开发者可以更好地理解如何在不同的开发场景中使用该方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.w3c.dom.Node 类的 isEqualNode() 方法的功能、参数及返回值,并通过多个实际代码示例来展示其具体应用。此方法用于检测两个节点是否相等,而不仅仅是判断它们是否为同一个对象。 ... [详细]
  • 本文探讨了如何在游戏启动画面中移除广告,特别是在游戏数据加载期间(大约5-6秒)广告会短暂显示的问题。通过调整XML布局和代码逻辑,可以实现广告的延迟加载或完全移除。 ... [详细]
  • 本文详细介绍了如何在Android应用中实现重复报警功能。示例代码可在以下路径找到:https://developer.android.com/samples/RepeatingAlarm/index.html。首先,我们将从Manifest文件开始分析。 ... [详细]
  • 使用TabActivity实现Android顶部选项卡功能
    本文介绍如何通过继承TabActivity来创建Android应用中的顶部选项卡。通过简单的步骤,您可以轻松地添加多个选项卡,并实现基本的界面切换功能。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 本文详细介绍了 `org.apache.tinkerpop.gremlin.structure.VertexProperty` 类中的 `key()` 方法,并提供了多个实际应用的代码示例。通过这些示例,读者可以更好地理解该方法在图数据库操作中的具体用途。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • Irish budget airline Ryanair announced plans to significantly increase its route network from Frankfurt Airport, marking a direct challenge to Lufthansa, Germany's leading carrier. ... [详细]
  • 如何将955万数据表的17秒SQL查询优化至300毫秒
    本文详细介绍了通过优化SQL查询策略,成功将一张包含955万条记录的财务流水表的查询时间从17秒缩短至300毫秒的方法。文章不仅提供了具体的SQL优化技巧,还深入探讨了背后的数据库原理。 ... [详细]
  • 本文介绍了如何通过C#语言调用动态链接库(DLL)中的函数来实现IC卡的基本操作,包括初始化设备、设置密码模式、获取设备状态等,并详细展示了将TextBox中的数据写入IC卡的具体实现方法。 ... [详细]
  • 深入理解Java SE 8新特性:Lambda表达式与函数式编程
    本文作为‘Java SE 8新特性概览’系列的一部分,将详细探讨Lambda表达式。通过多种示例,我们将展示Lambda表达式的不同应用场景,并解释编译器如何处理这些表达式。 ... [详细]
  • android开发分享荐                                                         Android思维导图布局:效果展示及使用方法
    思维导图布局的前身是树形布局,对树形布局基本使用还不太了解的朋友可以先看看我写的树形布局系列教程,了解了树形布局的使用方法后再来阅读本文章。先睹为快来看看效果吧,横向效果如下:纵向 ... [详细]
author-avatar
Bella团
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有