cocos creator 3.7.2使用shader实现图片扫光特效

简介

功能:图片实现扫光效果
引擎:cocos Creator 3.7.2
开发语言:ts

完整版链接

链接https://lengmo714.top/284d90f4.html

效果图

在这里插入图片描述

shader代码

// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
CCEffect %{
  techniques:
  - passes:
    - vert: sprite-vs:vert
      frag: sprite-fs:frag
      depthStencilState:
        depthTest: false
        depthWrite: false
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendDstAlpha: one_minus_src_alpha
      rasterizerState:
        cullMode: none
      properties:
        alphaThreshold: { value: 0.5 }

        # 自定义
        lightColor: { value: [1.0, 1.0, 0.0, 1.0], editor: {
          type: color,
          tooltip: "光束颜色" }}
        lightCenterPoint: { value: [0.2, 0.2], editor: { 
          tooltip: "光束中心点坐标" }}
        lightAngle: { value: 36.0, editor: { 
          tooltip: "光束倾斜角度" }}
        lightWidth: { value: 0.2, editor: { 
          tooltip: "光束宽度" }}
        enableGradient: { value: 1.0, editor: { 
          tooltip: "是否启用光束渐变。0:不启用,非0:启用" }}
        cropAlpha: { value: 1.0, editor: { 
          tooltip: "是否裁剪透明区域上的光。0:不启用,非0:启用" }}
        enableFog: { value: 0.0, editor: { 
          tooltip: "是否启用迷雾效果。0:不启用,非0:启用" }}
}%

CCProgram sprite-vs %{
  precision highp float;
  #include <builtin/uniforms/cc-global>
  #if USE_LOCAL
    #include <builtin/uniforms/cc-local>
  #endif

  in vec3 a_position;
  in vec2 a_texCoord;
  in vec4 a_color;

  out vec4 color;
  out vec2 uv0;

  vec4 vert () {
    vec4 pos = vec4(a_position, 1);

    #if USE_PIXEL_ALIGNMENT
      pos = cc_matView * pos;
      pos.xyz = floor(pos.xyz);
      pos = cc_matProj * pos;
    #else
      pos = cc_matViewProj * pos;
    #endif

    uv0 = a_texCoord;
    color = a_color;

    return pos;
  }
}%

CCProgram sprite-fs %{
  precision highp float;
  #include <builtin/internal/embedded-alpha>
  #include <builtin/internal/alpha-test>

  in vec4 color;

  #if USE_TEXTURE
    in vec2 uv0;
    #pragma builtin(local)
    layout(set = 2, binding = 11) uniform sampler2D cc_spriteTexture;
  #endif

  #if ENABLE_LIGHT
    uniform Light {
      // 光束颜色
      vec4 lightColor;

      // 光束中心点坐标
      vec2 lightCenterPoint;
      
      // 光束倾斜角度
      float lightAngle;

      // 光束宽度
      float lightWidth;

      // 启用光束渐变
      // ps:编辑器还不支持 bool 类型的样子,因此用float来定义
      float enableGradient;

      // 裁剪掉透明区域上的光
      // ps:编辑器还不支持 bool 类型的样子,因此用float来定义
      float cropAlpha;   

      // 是否启用迷雾效果
      // ps:编辑器还不支持 bool 类型的样子,因此用float来定义
      float enableFog;
    };

    /**
    * 添加光束颜色
    */
    vec4 addLightColor(vec4 textureColor, vec4 lightColor, vec2 lightCenterPoint, float lightAngle, float lightWidth) {
      // 边界值处理,没有宽度就返回原始颜色
      if (lightWidth <= 0.0) {
        return textureColor;
      }

      // 计算当前 uv 到 光束 的距离
      float angleInRadians = radians(lightAngle);

      // 角度0与非0不同处理
      float dis = 0.0;
      if (mod(lightAngle, 180.0) != 0.0) {
        // 计算光束中心线下方与X轴交点的X坐标
        // 1.0 - lightCenterPoint.y 是将转换为OpenGL坐标系,下文的 1.0 - y 类似
        float lightOffsetX = lightCenterPoint.x - ((1.0 - lightCenterPoint.y) / tan(angleInRadians));

        // 以当前点画一条平行于X轴的线,假设此线和光束中心线相交的点为D点
        // 那么 D.y = uv0.y
        // D.x = lightOffsetX + D.y / tan(angle)
        float dx = lightOffsetX + (1.0 - uv0.y) / tan(angleInRadians);

        // D 到当前 uv0 的距离就是
        // dis = |uv0.x - D.x|
        float offsetDis = abs(uv0.x - dx);

        // 当前点到光束中心线的的垂直距离就好算了
        dis = sin(angleInRadians) * offsetDis;
      } else {
        dis = abs(uv0.y - lightCenterPoint.y);
      }
      
      float a = 1.0 ;
      // 裁剪掉透明区域上的点光
      if (bool(cropAlpha)) {
        a *= step(0.01, textureColor.a);
      }

      // 裁剪掉光束范围外的uv(迷雾效果)
      if (!bool(enableFog)) {
        a *= step(dis, lightWidth * 0.5);
      }

      // 加入从中心往外渐变的效果
      if (bool(enableGradient)) {
        a *= 1.0 - dis / (lightWidth * 0.5);
      }

      // 计算出扩散范围内,不同 uv 对应的实际扩散颜色值
      vec4 finalLightColor = lightColor * a;

      // 混合颜色:在原始图像颜色上叠加扩散颜色
      //return textureColor * textureColor.a + finalLightColor;

        #if ENABLE_ORIGINCOLOR
          finalLightColor = textureColor + textureColor * a;
        #else
          finalLightColor = textureColor + finalLightColor;
          finalLightColor.a = textureColor.a;
        #endif

        return finalLightColor;
      }
  #endif
    
  vec4 frag () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      o *= CCSampleWithAlphaSeparated(cc_spriteTexture, uv0);
    #endif

    o *= color;
    ALPHA_TEST(o);

    #if ENABLE_LIGHT
      o = addLightColor(o, lightColor, lightCenterPoint, lightAngle, lightWidth);
    #endif
    
    return o;
  }
}%

使用方法

  • 手动创建一个材质
  • 将上面shader代码于材质进行绑定
  • 在ts脚本代码中控制扫光的移动

ts代码

import { _decorator, CCFloat, Component, Node, Sprite, Material, Vec2 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('NewComponent')
export class NewComponent extends Component {
    @property(Sprite)
    sprite !: Sprite;

    @property({ type: CCFloat, tooltip: "光束宽度" })
    lightWidth = 0.03;
    @property({ type: CCFloat, tooltip: "时间" })
    LoopTime = 1.0;
    @property({ type: CCFloat, tooltip: "TimeInterval" })
    TimeInterval = 2.0;

    /**记录时间 */
    private time: number = 0;
    /**精灵上的材质 */
    private material: Material = null!;
    private startPos = 0;
    private moveLength = 0;
    private Speed = 0;
    private dttime = 0;
    start() {
        this.time = 0;
        this.dttime = 0;
        this.material = this.sprite.getMaterial(0);
        this.startPos = -this.lightWidth / 2;
        this.moveLength = this.lightWidth + 1;
        this.Speed = this.moveLength / this.LoopTime / 2;
        this.time = this.startPos;
    }

    update(dt: number) {
        this.time += dt * this.Speed;
        this.dttime += dt;
        this.material.setProperty("lightCenterPoint", new Vec2(this.time, this.time));          //设置材质对应的属性
        if (this.dttime > this.LoopTime + this.TimeInterval) {
            this.time = this.startPos;
            this.dttime = 0;
        }
    }
}

完整demo

demo下载地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/440497.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

特性螺旋面的刀具设计记录

最近和成型类刀具杠上了&#xff0c;这不最近有小伙伴提供了两个比较特殊的螺旋面工件&#xff0c;通常称作阴、阳转子。具体形状如下&#xff1a; 阴转子 阴转子端面齿形没看出有什么特殊的&#xff0c;但是在轴剖面齿形是内凹的&#xff0c;这个是比较特殊的形式。 阳转子…

智慧园区综合运营数字化解决方案

1. 楼栋管理 2. 物业管理 3. 安防管理 4. 门禁管理 5. 停车管理 6. 能源管理 7. 环保管理 8. 园区生活服务 9. 招商管理 10. 收费中心 11. 园区地图 12. 门户网站 智慧园区软件方案&#xff1a;智慧园区软件解决方案&#xff0c;园区运营管理系统&#xff08;源码&#xff09;-…

【C++】C++模板基础知识篇

个人主页 &#xff1a; zxctscl 文章封面来自&#xff1a;艺术家–贤海林 如有转载请先通知 文章目录 1. 泛型编程2. 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.5 模板参数的匹配原则 3. 类模板3.1 类模板的定义格式3.2 类模板的实例化…

力扣刷题Days13--翻转二叉树(js)

目录 1,题目 2&#xff0c;代码 2.1递归思想-深度优先遍历 2.2迭代-广度优先遍历 3&#xff0c;学习与总结 1,题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 2&#xff0c;代码 2.1递归思想-深度优先遍历 我们从根节点开始&…

AI 应用之路:质疑汤姆猫,成为汤姆猫,超越汤姆猫

过去一年&#xff0c;我对 AI 应用的看法经历了这样一个过程&#xff1a;质疑汤姆猫&#xff0c;理解汤姆猫&#xff0c;成为汤姆猫&#xff0c;超越汤姆猫。 什么是汤姆猫&#xff1f;汤姆猫是 2010 年移动互联网早期的一款应用&#xff0c;迅速走红&#xff0c;又淡出视野。…

C++ · 代码笔记5 · 探索多态与虚函数

目录 前言011虚函数_使用基类指针实现覆盖特性012虚函数_使用引用实现覆盖特性013使用多态场景小例程020构成多态的条件030虚析构函数040纯虚函数051typeinfo运算符_获取类型信息052typeinfo_根据不同类型进行不同操作 前言 本笔记所涉及到的编程环境与 《C 代码笔记1 从C到C…

7款前端实战型项目特效分享(附在线预览)

分享7款实用性的前端动画特效 其中有canvas特效、css动画、svg动画等等 下方效果图可能不是特别的生动 那么你可以点击在线预览进行查看相应的动画特效 同时也是可以下载该资源的 CSS春节灯笼特效 基于CSS实现的灯笼特效 灯笼会朝左右两个方向来回的摆动着 以下效果图只能体现…

knife4j生产环境禁止打开页面

Knife4j是一个集Swagger2 和 OpenAPI3为一体的增强解决方案&#xff0c;官网地址&#xff1a;Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j 考虑到安全性问题&#xff0c;在实际服务部署到生产环境后就需要禁用到swagger页面的展示&#xff0c;这个时候只需…

Jmeter查看结果树之查看响应的13种详解方法

Jmeter查看结果树查看响应有哪几种方法&#xff0c;可通过左侧面板底部的下拉框选择: 01 Text 查看结果树中请求的默认格式为Text&#xff0c;显示取样器结果、请求、响应数据3个部分内容。 取样器结果&#xff1a; 默认Raw展示&#xff0c;可以切换为Parsed视图&#xff0c…

Selenium常见元素操作,学完就能上手

web端自动化测试在回归测试、兼容测试扮演着举足轻重的角色&#xff0c;作为web自动化测试工程师&#xff0c;日常工作主要的部分就是编写自动化测试用例代码&#xff0c;借助的开源框架来说&#xff0c;目前市场占有率较高的仍然是selenium。 如何使用selenium完成web页面元素…

算法---双指针练习-5(有效三角形的个数)

有效三角形的个数 1. 题目解析2. 讲解算法原理3. 编写代码 1. 题目解析 题目地址&#xff1a;有效三角形的个数 2. 讲解算法原理 算法的基本思想是首先对数组进行排序&#xff0c;然后使用三个指针left、right和cur&#xff0c;分别表示三个元素的索引。其中&#xff0c;left指…

PCIE UVM SVT

PCIE中存在UI概念,unit interval 定义为每个bit 传输需要的时间。 Introduction VC UVM VIP for PCIE 是一个兼容UVM验证方法学的高级验证组合以及数据类型的套件。 VC UVM VIP是基于uvm_agen 的架构图如下所示: svt_pcie_device_agent:它包含Driver,Target,Requeseter,I…

CDR(CorelDRAW)2024最新汉化注册补丁包下载

CorelDRAW 2024是一款功能强大的平面设计软件&#xff0c;广泛应用于图形设计、编辑照片以及创建网站等领域。凭借对高级操作系统的支持、多监视器查看和4K显示屏的兼容性&#xff0c;它让初始用户、图形专家、小型企业主和设计爱好者都能自信快速地交付专业级结果。 CorelDRA…

解决方案|珈和科技推出农业特色产业数字化服务平台

今年中央一号文件提出&#xff0c;鼓励各地因地制宜大力发展特色产业&#xff0c;支持打造乡土特色品牌。 然而&#xff0c;农业特色产业的生产、加工和销售仍然面临诸多挑战。产品优质不能优价&#xff0c;优质不能优用的现象屡见不鲜&#xff0c;产业化程度低、生产附加值不…

套接字编程 --- 一

目录 1. 预备知识 1.1. 端口号 1.2. 认识TCP协议 1.3. 认识UDP协议 1.4. 网络字节序 2. socket 2.1. socket 常见系统调用 2.1.1. socket 系统调用 2.1.2. bind 系统调用 2.1.3. recvfrom 系统调用 2.1.4. sendto系统调用 2.3. 其他相关接口 2.3.1. bzero 2.3.2…

智慧公厕的三大特点:信息化、数字化、智慧化

智慧公厕是以物联网、互联网、大数据、云计算等先进技术为支撑&#xff0c;对公共厕所的使用、运营、管理、养护进行全方位高效应用的创新型公厕。它具有三大显著特点&#xff1a;&#xff08;ZonTree中期&#xff09;信息化、数字化和智慧化。本文以智慧公厕源头实力厂家广州中…

【鸿蒙 HarmonyOS 4.0】常用组件:List/Grid/Tabs

一、背景 列表页面&#xff1a;List组件和Grid组件&#xff1b; 页签切换&#xff1a;Tabs组件&#xff1b; 二、列表页面 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“…

【PCIe 链路训练】之均衡(equalization)

1、概述 这篇文章简单介绍一下PCIE phy的均衡原理和过程,USB phy,ethernet phy这些高速的串行serdes也有相同或者相似的结构。可以不用太关注其中的细节,等到debug的时候可以查询协议,但是需要了解这个故事讲的大概内容。整个equalization过程是controller和phy一起配合完成…

什么是智慧公厕?智慧公厕设备有哪些

在现代社会&#xff0c;公共厕所作为城市基础设施的重要一环&#xff0c;承载着城市卫生、居民生活品质的重要责任。然而&#xff0c;传统公厕存在的问题仍然不可忽视&#xff1a;脏乱差、资源浪费、安全隐患等等。 为了解决这些问题&#xff0c;针对公共厕所日常使用、运营管…

go语言-k8s宿主信息采集运维脚本

背景 由于工作需要&#xff0c;需要采集k8s集群中的宿主相关信息&#xff0c;包括cpu,memory,lvm,标签等信息。通常作为SRE会主选shell或python脚本来实现。但最近我们团队主流开发语言已经切换到golang.所以本次尝试用go语言来写写运维脚本。 实现流程图 代码实现 package m…
最新文章