5.Shader

本文详细介绍了在OpenGL中如何使用in和out关键字在顶点着色器和片元着色器之间传递变量,以及如何利用uniform变量实现CPU到GPU的数据传输。同时,探讨了两种输入变量赋值的方法。

1.使用in、out关键字声明shader中的输入和输出变量

    为输入变量传值有两种方式:

        (1)在着色器中声明变量时使用location = t关键字指定顶点属性位置(顶点着色器需要提供一个额外的layout标识),在程序中通过t进行赋值

        (2)在程序中使用glGetAttribLocation(变量名)获取变量的地址,然后再进行赋值

2.在顶点着色器和片元着色器之间传值:

    如果我们打算从一个着色器向另一个着色器发送数据,在发送方着色器声明一个输出变量,在接收方着色器声明一个输入变量,当两个变量名字和类型一样时,OpenGL就会将两个变量链接在一起

const char * vertexShaderSource =
       "#version 330 core\n"
       "layout(location = 0) in vec3 aPos;\n"     
       "out vec4 vertexColor;\n"
       "void main(){\n"
       "gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0f);\n"
       "vertexColor = vec4(0.5,0.0,0.0,1.0);\n"
       "}\0";
const char* fragementShaderSource =
       "#version 330 core\n"
       "out vec4 FragColor;\n"
       "in vec4 vertexColor;"
       "void main(){\n"
       "FragColor = vertexColor;\n"
       "}";

3.uniform变量,uniform变量是从CPU应用向GPU发送数据的一种方式,uniform变量有以下两个特点:

    (1)uniform变量是全局变量,在所有着色器中都是独一无二的,而且可以被着色器程序的任意着色器在任意阶段访问

    (2)uniform会一直保存变量的数据,直到被更新或重置

定义uniform变量并赋值:(注意赋值前必须先使用程序)

const char* fragementShaderSource =
       "#version 330 core\n"
       "out vec4 FragColor;\n"
       "uniform vec4 mycolor;\n"
       "void main(){\n"
       "FragColor = mycolor;\n"
       "}\n\0";

main()
{
    //当变量不存在时返回-1
    int mycolorLocation = glGetUniformLocation(shaderProgram,"mycolor");
    glUniform4f(mycolorLocation,0.0f,color,0.0f,1.0f);
}

4.使用多个顶点属性,同webGL

在 Flutter 中,`Paint.shader` 属性用于为绘制操作提供着色器(Shader),从而实现渐变、图像映射等复杂的视觉效果。`Shader` 是通过 `ui.Shader` 对象创建的,通常可以基于颜色渐变、图像资源或自定义的着色器程序来生成。通过设置 `Paint.shader`,可以在 `Canvas` 上实现丰富的视觉效果。 在使用 `Paint.shader` 时,通常会结合 `Canvas.drawRect`、`Canvas.drawCircle` 或 `Canvas.drawPath` 等方法进行绘制。例如,可以通过 `Gradient` 类创建线性渐变或径向渐变,并将其赋值给 `Paint.shader` 属性,以实现平滑的颜色过渡效果。以下是一个使用线性渐变作为 `Paint.shader` 的示例: ```dart import 'package:flutter/material.dart'; class ShaderPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final Paint paint = Paint(); final Rect rect = Rect.fromLTRB(0, 0, size.width, size.height); // 创建线性渐变 paint.shader = ui.Gradient.linear( Offset(0, 0), Offset(size.width, size.height), <Color>[Colors.red, Colors.blue], ); // 使用带有 Shader 的 Paint 进行绘制 canvas.drawRect(rect, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => true; } ``` 此外,还可以使用 `ImageShader` 来将图像映射到绘制区域。`ImageShader` 允许将图像作为纹理应用到绘制路径上,适用于实现图像平铺、纹理填充等效果。创建 `ImageShader` 需要一个 `Image` 对象和采样方式(如 `TileMode`),示例如下: ```dart final Image image = // 获取图像资源 paint.shader = ImageShader(image, TileMode.repeated, TileMode.repeated, Matrix4.identity().storage); ``` 需要注意的是,在某些情况下,使用 `Paint.shader` 可能会影响性能,尤其是在复杂路径或大量绘制操作中。因此,建议在实际开发中根据需求合理使用 `Paint.shader`,并结合 `CustomPainter` 和 `Canvas` 的能力进行优化[^3]。 ### 相关问题 1. 如何在 Flutter 中实现径向渐变效果? 2. Paint.shader 与 CustomPainter 之间如何协同工作? 3. ImageShader 在 Flutter 中的应用场景有哪些? 4. 使用 Paint.shader 时如何优化性能? 5. 如何在 Flutter 中使用自定义着色器(Shader)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值