你相信光吗?2D 后效与光照技术分享!

很多朋友提到后效,就会想起那些 3D 游戏大作,但实际上,后效在 2D 游戏开发中的应用也是非常广泛的。
恰当地使用后效,可以使一款 2D 游戏的画质提升好几个台阶。
今天邀请到了社区大佬 wing,给大家分享一下 2D 后效框架相关的技术要点。

1275cbdeb59eea56dfb955988f61d73d.jpeg

什么是后处理效果

后处理效果简称后效,用于对渲染结果做进一步的处理,以实现许多高级效果和特殊效果。
通俗的解释就是对游戏画面进行 PS,在游戏中属于一种不可获缺的功能,常用于提升游戏画质与表现。

以下是一些常用后效:

  1. 模糊效果:可以用于实现景深、运动模糊等效果。

  2. 辉光效果:可以增加游戏元素的发光效果,提升游戏的视觉冲击力。

  3. 色调映射效果:可以调整游戏的色彩风格,表达不同的情绪和氛围。

  4. 扭曲效果:可以创建独特的变形效果,增加游戏的艺术感和创意。

  5. 颜色校正效果:可以调整游戏的整体色调和对比度,使画面更加饱满和生动。

f49484bf494f231922b75ffa29589935.jpeg

2D 后效方案解析

Cocos Creator 目前没有内置支持 2D 阶段的后处理,因此需要大家各显神才能通达到渲染目标。

用得最多的方式就是将相机渲染到一张 RenderTexture(以下简称 RT) 中,再显示到一个 Sprite 上。

这是一个古老而实用的解决方案,但是这样会对开发流程有一定影响且看起来不那么优雅。

参考社区大佬 @玄烨@二喵给终极解决方案,我们可以通过代码,将相机渲染的 RT 在处理后直接显示到最终窗口上。由于是通过代码创建一个矩形渲染到最上层,对于使用者来说是无感的,既优雅又方便。

渲染流程如下所示:

b5fc1771da1c03355a5af48427b87dec.jpeg

这里奉上关键代码:

let device = director.root.device;let renderPipeline = director.root.pipeline;let pso = PipelineStateManager.getOrCreatePipelineState(device, pass, pass.getShaderVariant(), __renderPass, __quad);let cmd = renderPipeline.commandBuffers[0];cmd.beginRenderPass(__renderPass, destination.window.framebuffer, renderArea, __clearColors, 0, 0);cmd.bindDescriptorSet(pipeline.SetIndex.GLOBAL, renderPipeline.descriptorSet);cmd.bindDescriptorSet(pipeline.SetIndex.MATERIAL, pass.descriptorSet);cmd.bindPipelineState(pso);cmd.bindInputAssembler(__quad);cmd.draw(__quad);cmd.endRenderPass();

好啦!大家知道原理了,是不是特别简单,有了核心技术,剩下的就是怎么去组织它,让它用起来更趁手,于是就有了如下几个通用接口 PP_Graphics

/*** 通用后处理接口,通过一个材质pass处理一张至目标纹理上*/
blitP(source: RenderTexture, destination: IRenderTexture, pass: renderer.Pass, renderArea: gfx.Rect = null)/*** 拷贝纹理*/
blit(source: RenderTexture,  destination: IRenderTexture,  renderArea: gfx.Rect = null )/*** 用一种颜色清除纹理*/
clear(destination: IRenderTexture,color: IVec4Like,renderArea: gfx.Rect = null)/*** 翻转纹理*/
flip(source: RenderTexture,destination: IRenderTexture,flipX: boolean,flipY: boolean,renderArea: gfx.Rect = null)

整个后处理渲染框架都是基于以上这几个接口,那么我们继续完善流程,以方便我们直接使用或者扩展更多渲染效果:

969ec762d32c12c0fc8d51884e871de1.png

其中:

  • PP_Graphics 包含上述各种基础接口

  • PostProcessingMgr 管理 PostProcessing 以及后处理用到的 RenderTexture

  • PostProcessing 绑定在相机上,用于接管相机的渲染结果,并用 RT 执行各种效果,并最终输入到屏幕上

  • IPPEffect 是最终的效果处理模块,可以按自己的需求进行排列组合

使用简介

基于以上流程,框架中包含了 10 多种基础效果,使用起来也比较简单,这里以窗口背景模糊为例:

1. 添加 Layer

先添加一个 UI 层,用于分离不同相机渲染的对象, 这里我添加了一个 UI_2D_1 的层级:62dcd8ad94d452628136e9f2d70c82c2.png

2. 创建两个 Canvas

我们需要创建两个 Canvas,并将两个 Canvas 中的节点放于不同的 layer 中:

背景放在 UI_2D_1 层中,用于模糊:bf235859b823c6eb371813d601592619.png

弹窗放入 UI_2D 层中:1fb5fd128d28dddd6f05ac244fd6dde6.png

3. 修改相机的可见层级

Canvas 下的相机只用渲染所在 Canvas 中的层级即可。

这里注意下,一般一个流程(2d、3d)的开始只需清屏方式为 DEPTH_ONLY。但是前面如果没有任何相机渲染,这时就需要 SOLID_COLOR 咯;这里相机 1 可见设置为 SolidColor, 相机 2 则为DepthOnly:201ecdace6f6865fd15869e5363fa141.png03b1f19f8a0edfbccc953f9deacffc2d.png

4. 对相机添加后处理处理

这里只用对背景模糊,即只用处理 camera1 渲染内容,在 camera 上添加组件。

PostProcessing 用于开启后处理 PPE_Blur 用于模糊:ae686210b076051a69ef96269d0474ea.png

启动预览,可以看到模糊功能就加好啦。0031ef8f4b72196b7e32e8f77db5fd0a.jpeg

自定义后效

后效的扩展也很方便,只需要如下几个资源、代码:

  • 一个后处理 shader

  • 一个绑定 shader 的材质球

  • 一个后处理扩展 ts 文件,用于给材质球传参

以下用一个屏幕变灰的效果做为例子:

1. 添加一个后处理 shader

precision highp float;  #include <pp-shared-ubos>in vec2 v_uv;uniform sampler2D mainTexture;#pragma define intensity matParams.xconst vec3 weight = vec3(0.2126, 0.7152, 0.0722);vec3 Grayscale(in vec3 o, float value){float lumin = dot(o, weight);vec3 final = mix(o, vec3(lumin), value);return final;}vec4 frag() {vec4 pixel = texture(mainTexture, v_uv);pixel.rgb = Grayscale(pixel.rgb, intensity);return pixel;}

2. 添加并编写脚本

编写对应的后处理脚本文件,用于控制材质球参数或者对图形进行多次处理,并暴露相关属性。

在框架中,后处理组件只需要继承 PPE_Base 类即可,一下是图像变灰的后处理组件的实现,找到相关材质球,并在 apply 函数中设置材质的属性即可:

*** 灰度*/
@ccclass('PPE_Grayscale')
export class PPE_Grayscale extends PPE_Base {@property({ range: [0, 1], slide: true, step: 0.01, override: true })intensity: number = 1;get materialPath() {return "materials/pp-grayscale";}public apply(source: RenderTexture, destination: IRenderTexture): void {let pass = this.material.passes[0];PP_Graphics.setUniform(pass, "intensity", this.intensity);PP_Graphics.blitP(source, destination, pass);}
}

3. 创建材质

使用对应的 Shader 创建材质球,放入统一的材质文件夹下,方便后处理框架加载。也可以在编辑器中将材质球拖拽到模块的材质槽中。7880afd12e414085271868ae4ec0b946.png

4. 调参、预览

在组件中调整好参数后,启动预览,即可获得自己想要的效果。00c4430e7374c46ced9244c0cad3fcd6.png

意外的惊喜(2D 光照效果)

588c3c4feb11f95addb6a1f5528ece9e.png

相信不久之前,有人已经看过这张动图了。这是用 Cocos Creator 创建的一个 2D 灯光效果,虽然不是正儿八经的光照系统,但是对于不少项目已经完全够用了,毕竟光嘛,就是图片的局部提亮。

其实早在论坛中就有不少人需要增加 2D 光照,大家给的方案也基本就是后处理中加光照点位。技术不复杂,但是点位的数量或多或少是有限制的,而且调试起来也比较麻烦。

当我将 2D 后处理框架做出来后的一天,我忽然有想到这个问题,既然我的 mask 已经实现,那不就一个妥妥的一个灯光效果嘛,只是数量太少,只支持一个。

dc3fc345b7f829843d2b2091f0d4c3d1.png

那如果我一张图来做为 mask 的遮罩呢?是不是灯光数量就无限了?这和延迟渲染是一个逻辑呀!基于这个想法,当晚就进行了一波测试,事实上这个技术方案更简单,不会儿就验证成功(当然中间有颜色叠加的坑,需要一顿调试),现在流程就变成了:

4f55d365392e20d79ebf634bb685cceb.jpeg

现在我们就得到一个 Cocos Creator 的 2D 光照系统,我找了张图测试了一番。

嘿,效果还不错,支持无限灯光数量不说,连粒子都可以作为光源,还支持各种异型灯光效果:

  • 一个相机渲染背景

  • 一个相机只渲染灯光,并绑定上后处理器,添加 2D 灯光后处理模块

6edf79a497ab7acb8640e25fe7b27fd1.png
  • 运行就可以看到效果

3a6b0b0003b97c0a9225f11c300ca36b.png

结语

3e7d96e86a30640981a931372f5089ec.jpeg

大家好,我是 wing,坐标成都,一个 35+ 的老年人。曾经游走于各种引擎之间,目前主用 Cocos。

平时主要工作是解决公司各个项目中的技术难题,也会在业余时间研究和储备各类技术方案,让公司的 Cocos 框架更通用。

这个项目本来也是无心插柳,一开始只是为了解决自己项目中的一个小问题。@二喵觉得将这个做成一个通用的解决方案,能让我更了解引擎的渲染流程,我就试试做了看。

没想到做了以后发现后处理是一个如此好玩的事情,可以让画面朝自己想要的效果表现,只需要控制各种参数即可。

最终灯光系统也是意外之喜,我获得了一次技能提升,也为社区做了少许贡献,也让需要此功能来表现游戏氛围的开发者和项目有了一条捷径。

感谢大家的阅读,希望能够给有需要的开发者们带来一些帮助!

听懂,掌声!

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

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

相关文章

力扣题目学习笔记(OC + Swift)16. 最接近的三数之和

16. 最接近的三数之和 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 排序 双指针 思路同15. 三数之和 简单地使用三重循环枚举所有的三…

微信小程序实现一个简单的登录功能

微信小程序实现一个简单的登录功能 功能介绍login.wxmllogin.jsuserInfo.wxmluserInfo.js解析 功能介绍 微信小程序实现一个简单的登录功能。包括一个登录页面和一个用户信息展示页面。在登录页面中输入用户名和密码&#xff0c;点击登录按钮进行验证&#xff0c;如果验证成功&…

MyBatis ORM映射

MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系&#xff0c;二者不同时无法自动ORM 因此需要使用到ORM映射。 共有两种解决办法&#xff1a;1.列的别名 2.结果映射 1.列的别名 在SQL中使用 as 为查询字段添加列别名&#xff0c;以匹配属性名 public List<…

nodejs+vue+微信小程序+python+PHP高校成绩分析系统-计算机毕业设计推荐

综合购物商城管理经历和对网上信息归纳整理的结果&#xff0c;在实际应用中&#xff0c;将用户分为两种&#xff1a;管理员和高校成绩分析系统综合网络空间开发设计要求。目的是将高校成绩分析从传统管理方式转换为在网上管理&#xff0c;完成高校成绩分析管理的方便快捷、安全…

spring boot3.2 集成 es 8.x 版本工具类 支持认证与非认证的方式( jdk21)

主要maven 依赖 <dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.11.2</version></dependency> 工具类如下 import co.elastic.clients.elasticsearch.Elastics…

pyCharm 创建一个FastApi web项目,实现接口调用

FastApi和Django区别 我这边演示项目使用的fastApi作为web框架&#xff0c;当然主流一般都是使用Django做web框架&#xff0c;但是Django是一个重量级web框架他有很多组件&#xff0c;如授权&#xff0c;分流等全套web功能。我这边呢只需要有个接口可以被别人调用&#xff0c;…

【超详细前后端项目搭建】前端vue3+ts项目(引入ElementPlus、Axios)、后端springboot搭建(创建接口操作mysql数据库)实现前后端联调

目录 前言一、前端项目1、使用vue脚手架创建项目1.1检查vue版本1.2 使用vue脚手架创建项目 2、删除项目多余文件&#xff0c;修改配置项目2.1、删除以下文件2.1、在views下创建index文件2.2、修改router/index.ts路由文件&#xff1a;2.3、修改App.vue文件&#xff1a;2.4、初始…

气候变化与环境保护:全球研究与未来趋势

导言 气候变化和环境保护是当今社会亟待解决的全球性难题。本文将深入探讨这一主要流行研究方向的发展历程、遇到的问题、解决过程&#xff0c;以及未来的可用范围&#xff0c;着重分析在各国的应用和未来的研究趋势&#xff0c;以探讨在哪些方面能够取得胜利&#xff0c;以及在…

大数据学习(29)-spark on yarn底层原理

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

PySpark中DataFrame的join操作

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

期货开平规则(期货交易开平规则解析)

什么是期货开平规则 期货开平规则&#xff0c;简单来说是指期货交易中的开仓和平仓所遵循的一系列规定。具体而言&#xff0c;开仓是指买入或卖出期货合约&#xff0c;建立一个新的持仓&#xff1b;平仓则是指买入或卖出相应数量的期货合约&#xff0c;用以解除原有持仓。开平…

什么是数据仪表板?数据可视化仪表盘怎么制作?

在数据经济时代&#xff0c;分析数据是每个企业做出最佳决策的关键。但是&#xff0c;手动分析和解释大量数据是不可行的。数据可视化对于分析数据中存在的各种有价值信息至关重要&#xff0c;包括可见趋势和隐藏趋势等。仪表盘显示可视化趋势和信息&#xff0c;例如 KPI、趋势…

xlsx-style使用中常见问题及解决办法

问题1. Can‘t resolve ‘./cptable‘ in ‘xxx\node_modules_xlsx 在vue.config.js中引入以下代码 configureWebpack: {externals: {./cptable: var cptable},}, 问题2. Can’t resolve ‘fs’ 在vue.config.js中引入以下代码 module.exports defineConfig({transpileDepe…

简易实现 STL--list

实现 list 的主要思想及过程 首先&#xff0c;实现过程中的所有代码必须放在自己定义的命名空间中。 定义一个结点的结构体类模板&#xff0c;结点的数据类型就应该是模板类型 T&#xff0c;定义的 next指针和 prev指针都应该是模板指针类型&#xff0c;并且结构体类中药有构…

微信小程序中wx:if 和 hidden的区别

wx:if 和 hidden的相同点 wx:if 与 hidden 都用来控制小程序元素的显示的 不同点 wx:if 1. 条件为 true 时显示 2. 当元素显示时渲染 3. 元素变为不显示时销毁元素 hidden&#xff1a; 1. 条件为 false 时显示 2. 当元素显示时渲染 3. 元素变为不显示时保留元素 4. 相…

2017年第六届数学建模国际赛小美赛A题飓风与全球变暖解题全过程文档及程序

2017年第六届数学建模国际赛小美赛 A题 飓风与全球变暖 原题再现&#xff1a; 飓风&#xff08;也包括在西北太平洋被称为“台风”的风暴以及在印度洋和西南太平洋被称为“严重热带气旋”&#xff09;具有极大的破坏性&#xff0c;往往造成数百人甚至数千人死亡。   许多气…

UE4移动端最小包优化实践

移动端对于包大小有着严苛的要求,然而UE哪怕是一个空工程打出来也有90+M,本文以一个复杂的工程为例,探索怎么把包大小降低到最小。 一、工程简介 工程包含代码、插件、资源、iOS原生库工程。 二、按官方文档进行基础优化 官方文档 1、勾选Use Pak File和Create comp…

YOLOv5性能评估指标->mAP、Precision、Recall、FPS、Confienc (讲解论文关注的主要指标)

简介 这篇博客&#xff0c;主要给大家讲解我们在训练yolov5时生成的结果文件中各个图片及其中指标的含义&#xff0c;帮助大家更深入的理解&#xff0c;以及我们在评估模型时和发表论文时主要关注的参数有那些。本文通过举例训练过程中的某一时间的结果来帮助大家理解&#xf…

npm安装依赖报错ERESOLVE unable to resolve dependency tree(我是在taro项目中)(node、npm 版本问题)

换了电脑之后新电脑安装包出错 &#x1f447;&#x1f447;&#x1f447; npm install 安装包报错 ERESOLVE unable to resolve dependency tree 百度后尝试使用 npm install --force 还是报错 参考 有人说是 node 版本和 npm 版本的问题 参考 新电脑 node版本&#xff1a;16.1…

kotlin第三方库记录

一、测试 除了JUnit与TestNG&#xff0c;下面两个框架提供了用kotlin编写测试的更有表现力的DSL 1.KotlinTest&#xff08;https://github.com/kotlintest/kotlintest&#xff09;——灵活的测试框架&#xff0c;它的灵感来自于ScalaTest&#xff0c;支持多种不同的编写测试的…