Flutter & GLSL - 贰 | 从坐标到颜色

上一篇 《 Flutter 绘制集录 | Shader 让绘制无限强大 - 壹》 介绍了 Flutter 本身支持 GLSL 语言 进行 Shader 着色器的编写。这给 Flutter 的绘制能力增加了无限的可能。GLSL 着色器代码是一个比较独立的知识体系,接下来的几篇文章将会基于 实际使用 向大家进行介绍。


1. 坐标与颜色

我们都知道屏幕上的展示的内容都是由一个个 像素点 构成的。

  • 每个像素点包含 颜色 的信息;
  • 每个像素点分布在屏幕坐标系上,还拥有位置 坐标 信息。

本质上是建立一种 坐标颜色 的映射关系;也可以说 GLSL 是在 通过代码控制像素


颜色在 GLSL 种通过四维向量 vec4 进行表示, 分量代表 rgba 四个通道的数值。取值范围均在 [0,1] 之间,相当于对 [0~255] 表示的颜色进行单位化:


2. 认识着色器代码

下面是一个最简单的 GLSL 着色器代码,永远输出单一的颜色:

  • #version 460 core : 是声明 GLSL 的版本。
  • precision mediump float; : 声明浮点数的精度。
  • out 关键字用于定义输出颜色,这里四维向量 fragColor 表示输出色。
  • main 函数中的代码是将被运行在 GPU 上的着色程序。
c 复制代码
---->[shaders/color.frag]----
#version 460 core
precision mediump float;
out vec4 fragColor;

void main() {
    fragColor = vec4(5, 83, 177, 255) / 255;
}

这里为 fragColor 赋值为拾取的颜色,即可展示出对应的蓝色:


3. 坐标的使用

上面每个像素坐标输出色全是一种,未免有些单调。现在来了解一下坐标在 GLSL 程序中的作用,完成下面的小需求:

将小于宽度一半的区域着成 蓝色 ;大于宽度一半的区域着成 红色

在 Flutter 的着色器中,引入 <flutter/runtime_effect.glsl> 通过 FlutterFragCoord() 得到坐标。在着色器程序执行时,会 逐一扫描 区域内的每一个像素,输出颜色。

比如这里画板的尺寸是 400*200,一共有 80000 的像素点,这段着色器代码的功能就是为这 80000 个像素安排颜色。

下面代码中 coo 表示当前运算像素的坐标,我们可以很轻松地根据 coo.x 横坐标进行校验:小于 200 输出色设为蓝色;大于或等于 200 ,输出色设为红色。 即可完成需求:

c 复制代码
#version 460 core
precision mediump float;
#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

void main() {
    vec2 coo = FlutterFragCoord().xy;
    if (coo.x < 200) {
        fragColor = vec4(4, 83, 177, 255) / 255;
    } else {
        fragColor = vec4(218, 13, 21, 255) / 255;
    }
}

同理,我们可以根据对坐标的控制。在屏幕上输出四种颜色,如下所示:

c 复制代码
#version 460 core
precision mediump float;
#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

vec4 blue = vec4(4, 83, 177, 255) / 255;
vec4 red = vec4(218, 13, 21, 255) / 255;
vec4 yellow = vec4(250, 193, 21, 255) / 255;
vec4 green = vec4(38, 152, 70, 255) / 255;

void main() {
    vec2 coo = FlutterFragCoord().xy;
    if(coo.x<200){
        if(coo.y<100){
            fragColor = blue;
        }else{
            fragColor = red;
        }
    }else {
        if(coo.y<100){
            fragColor = yellow;
        }else{
            fragColor = green;
        }
    }
}

4. 坐标的归一化

在上面的计算中,我们使用了画布尺寸参与计算。这并不是很好,因为画板的尺寸可以随意地变化,想让一个着色器具有普适性,一般会将坐标系归一,也就是横纵坐标都在 [0~1] 之间。完成归一也很简单,只要将坐标除以尺寸即可:

如下现在定义了 vec2 size, coo 坐标在计算时除以尺寸,就可以单位化。下面的指示器代码中,将红色值设置为 coo.x ,就可以得到如下的黑到红的渐变色,想一想这是为什么呢?

c 复制代码
#version 460 core
precision mediump float;
#include <flutter/runtime_effect.glsl>

out vec4 fragColor;

void main() {
    vec2 size = vec2(400.0,200.0);
    vec2 coo = FlutterFragCoord().xy/size;
    fragColor = vec4(coo.x,0.0,0.0,1.0);
}

想象一下:

着色器代码逐行地计算区域内每一个像素的颜色,每一行中 coo.x 此时将从 [0~1] 改变。

坐标为 0 时颜色是 0,0,0,1 黑色;

坐标为 1 时,颜色是 1,0,0,1 红色;中间不断是 [0~1] 的过渡渐变。


相信通过这几个小例子,大家应该明白在 GLSL 着色器代码中坐标和颜色的作用了。可能有人会说,你最后定义的 size 不也是写死的嘛,别着急,下一篇将介绍如何通过 Flutter 代码,向 GLSL 代码传递参数。本篇就到这里,谢谢观看 ~

相关推荐
灯火不休ᝰ3 分钟前
[安卓] Kotlin中的架构演进:从MVC到MVVM
android·架构·kotlin
JMchen1234 分钟前
AR Core与CameraX的融合:测量应用从原理到实现
android·经验分享·程序人生·ar·移动开发·android studio·camerax
一起养小猫9 分钟前
Flutter for OpenHarmony 实战:2048游戏算法与优化深度解析
算法·flutter·游戏
June bug20 分钟前
【领域知识】一个休闲游戏产品(安卓和iOS)从0到1
android·ios
zgyhc205020 分钟前
【Android Audio】Android Audio有线设备插拔监听机制
android
ZHANG13HAO22 分钟前
android13 系统强制wifi连接到内网,假装具有互联网能力
android
2601_9498574327 分钟前
Flutter for OpenHarmony Web开发助手App实战:HTML参考
前端·flutter·html
2501_9151063232 分钟前
iOS 如何绕过 ATS 发送请求,iOS调试
android·ios·小程序·https·uni-app·iphone·webview
JMchen12337 分钟前
Android相机硬件抽象层(HAL)逆向工程:定制ROM的相机优化深度指南
android·开发语言·c++·python·数码相机·移动开发·android studio
一起养小猫1 小时前
Flutter for OpenHarmony 实战:扫雷游戏算法深度解析与优化
算法·flutter·游戏