Cocos Creator 3.8 修改纹理像素值

news2025/1/10 15:15:01

修改的代码:

import { _decorator, Component, RenderTexture, Sprite, Texture2D, ImageAsset, SpriteFrame, Vec2, gfx, director, log, math, v2 } from 'cc';

const { ccclass, property } = _decorator;



@ccclass('GradientTransparency')
export class GradientTransparency extends Component {

    public readPixels (texture:Texture2D, x = 0, y = 0, width?: number, height?: number) : Uint8Array | null {
        log('width:', width, ' height:', height);
        width = width || texture.width;
        height = width || texture.height;
        log('texture:', texture);
        const gfxTexture = texture.getGFXTexture();
        if (!gfxTexture) {
            return null;
        }
        const bufferViews: ArrayBufferView[] = [];
        const regions: gfx.BufferTextureCopy[] = [];
    
        const region0 = new gfx.BufferTextureCopy();
        region0.texOffset.x = x;
        region0.texOffset.y = y;
        region0.texExtent.width = width;
        region0.texExtent.height = height;
        regions.push(region0);
    
        const buffer = new Uint8Array(width * height * 4);
        bufferViews.push(buffer);
    
        director.root?.device.copyTextureToBuffers(gfxTexture, bufferViews, regions)
    
        return buffer;
    }

    public smoothstep(edge0: number, edge1: number, x: number): number {
        // 将 x 限制在 [edge0, edge1] 范围内
        //const t = Math.max(0, Math.min(1, (x - edge0) / (edge1 - edge0)));
        const t = Math.min(Math.max((x - edge0) / (edge1 - edge0), 0.0), 1.0);
    
        // 使用三次 Hermite 插值
        return t * t * (3 - 2 * t);
    }

    /**
     * 修改 Sprite 的透明度
     * @param sprite 目标 Sprite
     * @param points 给定的圆心点(UV 坐标,范围 [0, 1])
     * @param radius1 第一个透明度分界点的半径(完全透明半径)
     * @param radius2 第二个透明度分界点的半径(渐变透明半径)
     */
    modifySpriteAlpha(sprite: Sprite, points: Vec2[], radius1: number, radius2: number) {
        const spriteFrame = sprite.spriteFrame;

        if (!spriteFrame) {
            console.error("SpriteFrame 不存在!");
            return;
        }

        const texture = spriteFrame.texture;
        if (!texture) {
            console.error("Texture 不存在!");
            return;
        }

        // 创建 RenderTexture
        const renderTexture = new RenderTexture();
        renderTexture.reset({
            width: spriteFrame.width,
            height: spriteFrame.height,
        });

        // 获取像素数据
        log('spriteFrame:', spriteFrame);
        const pixels = this.readPixels(spriteFrame.texture as Texture2D, 0, 0, spriteFrame.width, spriteFrame.height);
        log('pixels:', pixels);

        const width = spriteFrame.width;
        const height = spriteFrame.height;

        // 最大不透明度
        const maxAlpha = 200;

        // 遍历每个像素
        for (let y = 0; y < height; y++) {
            for (let x = 0; x < width; x++) {
                const index = (y * width + x) * 4; // 每个像素的起始索引
                let alpha = pixels[index + 3]; // 当前像素的 alpha 通道

                // 将像素点转换为 UV 坐标
                const uv = new Vec2(x / width, y / height);

                // 计算与每个点的距离并修改透明度
                points.forEach(point => {
                    const distance = uv.clone().subtract(point).multiply(v2(width, height)).length(); // 距离(按像素计算)
                    //let realPoint = v2(point.x * width, point.y * height);
                    //const distance = Vec2.distance(realPoint, v2(x, y));
                    
                    if (distance < radius1) {
                        alpha = 0; // 完全透明
                    } else if (distance >= radius1 && distance < radius2) {
                        //alpha = 
                        alpha = this.smoothstep(radius1, radius2, distance) * maxAlpha;
                        /*
                        const t = (distance - radius1) / (radius2 - radius1); // 计算线性插值
                        const calculatedAlpha = (1 - t) * maxAlpha; // 渐变透明
                        alpha = Math.min(alpha, calculatedAlpha); // 重叠透明度处理,叠加上限为 128
                        */
                    } else {
                        alpha = Math.min(alpha, maxAlpha); // 超出范围,保持不透明度为 128
                    }
                });

                pixels[index + 3] = 255 - alpha; // 更新 alpha 通道
            }
        }

        // 创建新的 ImageAsset
        const newImageAsset = new ImageAsset();
        newImageAsset.reset({
            _data: pixels,
            _compressed: false,
            width: width,
            height: height,
            format: Texture2D.PixelFormat.RGBA8888,
        });

        // 创建新的 Texture2D
        const newTexture = new Texture2D();
        newTexture.image = newImageAsset;

        // 创建新的 SpriteFrame
        const newSpriteFrame = new SpriteFrame();
        newSpriteFrame.texture = newTexture;

        // 应用新的 SpriteFrame
        sprite.spriteFrame = newSpriteFrame;
    }
}

调用的代码:

import { _decorator, Component, Sprite, Vec2 } from "cc";
import { GradientTransparency } from "./fogImplement";

const { ccclass, property } = _decorator;

@ccclass('MainController')
export class MainController extends Component {
    @property(Sprite)
    targetSprite: Sprite = null; // 拖入目标 Sprite

    onLoad() {
        
    }

    onClick(){
        const gradientTransparency = this.getComponent(GradientTransparency);
        if (gradientTransparency && this.targetSprite) {
            // 设置两个 UV 坐标点
            const points = [new Vec2(0.5, 0.5)];  //, new Vec2(0.7, 0.7)
            const radius1 = 100; // 第一个分界点(完全透明)
            const radius2 = 200; // 第二个分界点(渐变透明)

            gradientTransparency.modifySpriteAlpha(this.targetSprite, points, radius1, radius2);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

读书笔记:分布式系统原理介绍

写在前面 已经大概三个月左右没有更新博客了&#xff0c;哈哈哈哈&#xff1b; 此博客是笔者在对《分布式系统原理介绍》进行概述&#xff0c;对于整个分布式系统协议的理解基于一些量化的指标考虑了数据的分布副本协议&#xff08;中心化/去中心化&#xff09;进行了总结&…

Dexcap复现代码数据预处理全流程(四)——demo_clipping_3d.py

此脚本的主要功能是可视化点云数据文件&#xff08;.pcd 文件&#xff09;&#xff0c;并通过键盘交互选择演示数据的起始帧和结束帧&#xff0c;生成片段标记文件 (clip_marks.json) 主要流程包括&#xff1a; 用户指定数据目录&#xff1a;检查目录是否存在并处理标记文件 -…

MBM指尖六维力触觉传感器:高灵敏度、低漂移,精准掌控力学世界

MBM指尖六维力触觉传感器是一种专为机器人设计的高性能传感器。它通过集成三轴力和三轴力矩的感知能力&#xff0c;能够精准捕捉复杂的力学信息。传感器采用MEMS与应变体复合测量技术&#xff0c;具备数字输出功能&#xff0c;显著降低漂移并减少安装偏移的影响。其紧凑轻便的设…

C#,图论与图算法,任意一对节点之间最短距离的弗洛伊德·沃肖尔(Floyd Warshall)算法与源程序

一、弗洛伊德沃肖尔算法 Floyd-Warshall算法是图的最短路径算法。与Bellman-Ford算法或Dijkstra算法一样&#xff0c;它计算图中的最短路径。然而&#xff0c;Bellman Ford和Dijkstra都是单源最短路径算法。这意味着他们只计算来自单个源的最短路径。另一方面&#xff0c;Floy…

为答疑机器人扩展问题分类与路由功能

1.意图识别 2. 构建路由模块 简单的意图识别 from chatbot import llmfrom config.load_key import load_key load_key()prompt 【角色背景】 你是一个问题分类路由器&#xff0c;需要识别问题的类型。 --- 【任务要求】 问题的类型目前有&#xff1a;公司内部文档查询、内…

spring boot启动源码分析(三)之Environment准备

上一篇《spring-boot启动源码分析&#xff08;二&#xff09;之SpringApplicationRunListener》 环境介绍&#xff1a; spring boot版本&#xff1a;2.7.18 主要starter:spring-boot-starter-web 本篇开始讲启动过程中Environment环境准备&#xff0c;Environment是管理所有…

Pandas-RFM会员价值度模型

文章目录 一. 会员价值度模型介绍二. RFM计算与显示1. 背景2. 技术点3. 数据4. 代码① 导入模块② 读取数据③ 数据预处理Ⅰ. 数据清洗, 即: 删除缺失值, 去掉异常值.Ⅱ. 查看清洗后的数据Ⅲ. 把前四年的数据, 拼接到一起 ④ 计算RFM的原始值⑤ 确定RFM划分区间⑥ RFM计算过程⑦…

【理论】测试框架体系TDD、BDD、ATDD、DDT介绍

一、测试框架是什么 测试框架是一组用于创建和设计测试用例的指南或规则。框架由旨在帮助 QA 专业人员更有效地测试的实践和工具的组合组成。 这些指南可能包括编码标准、测试数据处理方法、对象存储库、存储测试结果的过程或有关如何访问外部资源的信息。 A testing framewo…

FreeU: Free Lunch in Diffusion U-Net 笔记

FreeU: Free Lunch in Diffusion U-Net 摘要 作者研究了 U-Net 架构对去噪过程的关键贡献&#xff0c;并发现其主干部分主要在去噪方面发挥作用&#xff0c;而其跳跃连接主要是向解码器模块引入高频特征&#xff0c;这使得网络忽略了主干部分的语义信息。基于这一发现&#…

JAVA 使用apache poi实现EXCEL文件的输出;apache poi实现标题行的第一个字符为红色;EXCEL设置某几个字符为别的颜色

设置输出文件的列宽&#xff0c;防止文件过于丑陋 Sheet sheet workbook.createSheet(FileConstants.ERROR_FILE_SHEET_NAME); sheet.setColumnWidth(0, 40 * 256); sheet.setColumnWidth(1, 20 * 256); sheet.setColumnWidth(2, 20 * 256); sheet.setColumnWidth(3, 20 * 25…

【STM32】无源蜂鸣器播放音乐《千与千寻》,HAL库

目录 一、工程链接 二、简单介绍 主要特点&#xff1a; 应用&#xff1a; 驱动电路&#xff1a; 三、原理图 四、cubeMX配置 时钟配置 五、keil配置 六、驱动编写 演奏函数 主函数编写 七、效果展示 八、驱动附录 music.h music.c 一、工程链接 STM32无源蜂鸣…

在 Vue 3 集成 e签宝电子合同签署功能

实现 Vue 3 e签宝电子合同签署功能&#xff0c;需要使用 e签宝提供的实际 SDK 或 API。 e签宝通常提供针对不同平台&#xff08;如 Web、Android、iOS&#xff09;的 SDK&#xff0c;而 Web 端一般通过 WebView 或直接使用嵌入式 iframe 来加载合同签署页面。 下面举个 &…

04、Redis深入数据结构

一、简单动态字符串SDS 无论是Redis中的key还是value&#xff0c;其基础数据类型都是字符串。如&#xff0c;Hash型value的field与value的类型&#xff0c;List型&#xff0c;Set型&#xff0c;ZSet型value的元素的类型等都是字符串。redis没有使用传统C中的字符串而是自定义了…

如何用Python编程实现自动整理XML发票文件

传统手工整理发票耗时费力且易出错&#xff0c;而 XML 格式发票因其结构化、标准化的特点&#xff0c;为实现发票的自动化整理与保存提供了可能。本文将详细探讨用python来编程实现对 XML 格式的发票进行自动整理。 一、XML 格式发票的特点 结构化数据&#xff1a;XML 格式发票…

Linux——修改USB网卡设备节点名称

修改驱动&#xff1a; 测试&#xff1a; 参考资料&#xff1a; https://blog.csdn.net/ablexu2018/article/details/144868950

(STM32笔记)十二、DMA的基础知识与用法 第三部分

我用的是正点的STM32F103来进行学习&#xff0c;板子和教程是野火的指南者。 之后的这个系列笔记开头未标明的话&#xff0c;用的也是这个板子和教程。 DMA的基础知识与用法 三、DMA程序验证1、DMA 存储器到存储器模式实验&#xff08;1&#xff09;DMA结构体解释&#xff08;2…

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…

高斯函数Gaussian绘制matlab

高斯 约翰卡尔弗里德里希高斯&#xff0c;&#xff08;德语&#xff1a;Johann Carl Friedrich Gau&#xff0c;英语&#xff1a;Gauss&#xff0c;拉丁语&#xff1a;Carolus Fridericus Gauss&#xff09;1777年4月30日–1855年2月23日&#xff0c;德国著名数学家、物理学家…

vue的路由守卫逻辑处理不当导致部署在nginx上无法捕捉后端异步响应消息等问题

近期对前端的路由卫士有了更多的认识。 何为路由守卫&#xff1f;这可能是一种约定俗成的名称。就是VUE中的自定义函数&#xff0c;用来处理路由跳转。 import { createRouter, createWebHashHistory } from "vue-router";const router createRouter({history: cr…

如何在 Ubuntu 22.04 上使用 LEMP 安装 WordPress 教程

简介&#xff1a; 本教程旨在指导你如何在 Ubuntu 22.04 上使用 LEMP 栈安装 WordPress。 WordPress 是一个用 PHP 编写的开源内容管理系统。LEMP 栈是 Linux&#xff0c;NGINX&#xff0c;MySQL 和 PHP 的缩写。WordPress 非常用户友好&#xff0c;并提供了多种选项&#xff…