当前位置: 首页 > news >正文

Learn ComputeShader 07 Post Processing

这次我们将使用计算机着色器对图像进行后处理。

要进行后处理需要将渲染图像从cpu传递给gpu,并在gpu对图像进行处理然后传回cpu。

首先创建一个后处理基类BasePP

首先声明需要用到的属性。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[RequireComponent(typeof(Camera))]
public class BasePP : MonoBehaviour
{public ComputeShader shader = null;protected string kernelName = "CSMain";protected Vector2Int texSize = new Vector2Int(0,0);protected Vector2Int groupSize = new Vector2Int();protected Camera thisCamera;protected RenderTexture output = null;protected RenderTexture renderedSource = null;protected int kernelHandle = -1;protected bool init = false;protected virtual void Init(){if (!SystemInfo.supportsComputeShaders){Debug.LogError("It seems your target Hardware does not support Compute Shaders.");return;}if (!shader){Debug.LogError("No shader");return;}kernelHandle = shader.FindKernel(kernelName);thisCamera = GetComponent<Camera>();if (!thisCamera){Debug.LogError("Object has no Camera");return;}CreateTextures();init = true;}protected void ClearTexture(ref RenderTexture textureToClear){if (null != textureToClear){textureToClear.Release();textureToClear = null;}}protected virtual void ClearTextures(){ClearTexture(ref output);ClearTexture(ref renderedSource);}protected void CreateTexture(ref RenderTexture textureToMake, int divide=1){textureToMake = new RenderTexture(texSize.x/divide, texSize.y/divide, 0);textureToMake.enableRandomWrite = true;textureToMake.Create();}protected virtual void CreateTextures(){}protected virtual void OnEnable(){Init();}protected virtual void OnDisable(){ClearTextures();init = false;}protected virtual void OnDestroy(){ClearTextures();init = false;}protected virtual void DispatchWithSource(ref RenderTexture source, ref RenderTexture destination){}protected void CheckResolution(out bool resChange ){resChange = false;}protected virtual void OnRenderImage(RenderTexture source, RenderTexture destination){if (!init || shader == null){Graphics.Blit(source, destination);}else{CheckResolution(out _);DispatchWithSource(ref source, ref destination);}}}

初始化以后就会创建纹理,但是这个函数还没有完善。

首先设置纹理的宽度和高度,然后获取线程组的x和y的大小,这里GetKernelThreadGroupSizes的都三个参数out _表示忽略z 轴的线程组尺寸,这是 C# 语言中的一种方式,用于表示对某个输出值不感兴趣,不需要它的实际值。,然后创建两张纹理并传递给shader。

    protected virtual void CreateTextures(){texSize.x = thisCamera.pixelWidth;//返回摄像机视口的宽度和高度texSize.y = thisCamera.pixelHeight;if (shader){uint x, y;shader.GetKernelThreadGroupSizes(kernelHandle, out x, out y,out _);groupSize.x = Mathf.CeilToInt((float)texSize.x / (float)x);groupSize.y = Mathf.CeilToInt((float)texSize.y / (float)y);}CreateTexture(ref output);CreateTexture(ref renderedSource);shader.SetTexture(kernelHandle, "source", renderedSource);shader.SetTexture(kernelHandle, "output", output);}

下面就是要获取到渲染的纹理并传递到GPU

 OnRenderImage(RenderTexture source, RenderTexture destination)这个函数可以获取摄像机渲染后的图像到source,并通过对原图像的一系列处理之后设置到destination上。

OnRenderImage 是 Unity 中的一个特殊回调函数,用于在摄像机完成渲染之后对图像进行后处理。它是在摄像机渲染过程的最后阶段被自动调用的。你不需要手动调用这个函数,而是由 Unity 引擎在渲染管线中自动调用。

    protected virtual void OnRenderImage(RenderTexture source, RenderTexture destination){if (!init || shader == null){Graphics.Blit(source, destination);}else{CheckResolution(out _);DispatchWithSource(ref source, ref destination);}}

接着我们继续完善checkresolution和dispatchwithsource函数。

如果没有设置texsize那么就执行createtextures函数设置纹理大小

    protected void CheckResolution(out bool resChange ){resChange = false;if (texSize.x != thisCamera.pixelWidth || texSize.y != thisCamera.pixelHeight){resChange = true;CreateTextures();}}

首先将源纹理传递到shader,然后给shader分配线程组,然后将shader处理后的纹理传递到destination

    protected virtual void DispatchWithSource(ref RenderTexture source, ref RenderTexture destination){Graphics.Blit(source, renderedSource);shader.Dispatch(kernelHandle, groupSize.x, groupSize.y, 1);Graphics.Blit(output, destination);}

接着我们书写一个简单的后处理示例

我们只是在代码中将原图像的颜色乘上一个shade调整图像的亮度

void Highlight(uint3 id : SV_DispatchThreadID)
{float4 srcColor = source[id.xy];float4 color   =srcColor*shade;output[id.xy] = color;
}

效果展示:

接着我们想要让角色周围高亮显示,但是其它地方仍然是变暗一些。

首先在cpu获取角色的位置并且转换到屏幕坐标,然后传递给shader。

 protected override void OnRenderImage(RenderTexture source, RenderTexture destination){if (!init || shader == null){Graphics.Blit(source, destination);}else{if (trackedObject && thisCamera){Vector3 pos = thisCamera.WorldToScreenPoint(trackedObject.position);//将世界坐标转换为屏幕坐标center.x = pos.x;center.y = pos.y;shader.SetVector("center", center);}bool resChange =false;CheckResolution(out _);if (resChange) SetProperties();DispatchWithSource(ref source, ref destination);}}

在shader中检测像素是否在角色周围,然后根据和角色的距离对颜色进行插值。如果距离大于半径完全是变暗的颜色,小于半径就是高亮显示。

float inCircle( float2 pt, float2 center, float radius, float edgeWidth ){float len = length(pt - center);return 1.0 - smoothstep(radius-edgeWidth, radius, len);
}[numthreads(8, 8, 1)]
void Highlight(uint3 id : SV_DispatchThreadID)
{float4 srcColor = source[id.xy];float4 shadedSrcColor   =srcColor*shade;float4 highlight = inCircle((float2)id.xy,center.xy,radius,edgeWidth);float4 color =lerp(shadedSrcColor,srcColor,highlight);output[id.xy] = color;
}

效果:

相关文章:

Learn ComputeShader 07 Post Processing

这次我们将使用计算机着色器对图像进行后处理。 要进行后处理需要将渲染图像从cpu传递给gpu&#xff0c;并在gpu对图像进行处理然后传回cpu。 首先创建一个后处理基类BasePP 首先声明需要用到的属性。 using System.Collections; using System.Collections.Generic; using …...

初始QT!

作业&#xff1a;了解QT文件夹初始代码的意义 QT core gui #QT工程所需得类库 core是核心库 gui图形化界面相关库类 greaterThan(QT_MAJOR_VERSION, 4): QT widgets #版本超过4.0会加上widgetsCONFIG c11 #该编辑器支持c11后的版本 # The following define makes you…...

全国大学生数据建模比赛——深度学习

全国大学生数学建模比赛中&#xff0c;深度学习可以成为解决复杂问题的有力手段。 一、深度学习的优势在比赛中的体现 强大的模式识别能力&#xff1a;深度学习模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;和循环神经网络&#xff08;RNN&#xff09;&#xff0…...

Qt技巧(二)-滑动界面,轮询控件,循环操作控件

在Qt界面开发过程中&#xff0c;我们常常要对同类部件&#xff0c;具有同样功能的一系列部件进行操作&#xff0c;比如&#xff1a; 这个页面该怎么设计&#xff0c;中间的几个选项该怎么操作&#xff1f; 我们在主工程中添加一个设计师界面类&#xff0c;类名设置为“BrandF…...

003——单链表

1.链式存储的特点 逻辑&#xff08;通过指针实现&#xff09;上相邻&#xff0c;物理上可相邻可不相邻 2.结点&#xff08;节点都可以&#xff09; 4&#xff08;&8&#xff09; 8&#xff08;&6&#xff09; 6&#xff08;&1&#xff09; 1&#xff08;&…...

XILINX平台下LINUX DMA驱动调研

专栏目录 高质量文章导航-持续更新中-CSDN博客 基础概念 VA:virtual address称为虚拟地址, PA:physical address称为物理地址。 CPU通过地址来访问内存中的单元,如果CPU没有MMU,或者有MMU但没有启动,那么CPU内核在取指令或者访问内存时发出的地址(此时必须是物理地址…...

Oracle数据库安装和配置指南

Oracle数据库是一款功能强大的企业级关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于各种规模的企业和组织。其强大的性能和丰富的功能使其成为数据库管理的首选解决方案之一。以下是关于如何安装和配置 Oracle 数据库的详细指南。 一、准备工作 在开…...

制造业中工艺路线(工序)与产线(工作中心)关系

一.工艺路线与生产线是数字孪生中的虚实关系&#xff1a; 1.工艺路线为虚&#xff0c;生产线体为实&#xff1b; 2.工艺路线指导生产线的生产组织&#xff0c;生产线承载工艺路线的能力&#xff0c;把虚拟的生产信息流变成真实的产流。 二.工艺路线与生产线是数字孪生中互为“…...

目标跟踪算法——ByteTrack算法原理解析

文章目录 ByteTrack1. ByteTrack算法步骤&#xff1a;2. 算法解释2.1 模型初始化2.2 模型更新算法流程2.2.1 检测结果划分&#xff0c;划分为高分和较低分段2.2.2 高分段处理手段2.2.3 最优匹配与未匹配划分2.2.4 低分框再匹配2.2.5 未确认轨迹处理2.2.6 更新状态 2.3 匈牙利匹…...

C语言编译的过程

文章目录 1. 预处理&#xff08;Preprocessing&#xff09;2. 编译&#xff08;Compilation&#xff09;3. 汇编&#xff08;Assembly&#xff09;4. 链接&#xff08;Linking&#xff09;总结 c语言通过编译器直接编译成机器语言程序。 C语言程序的编译过程通常分为四个主要步…...

前端面试题——栈与队列、动态路由、链表

栈、队列与链表 Java数据结构栏目总结-CSDN博客 栈&#xff08;Stack&#xff09; 栈是一种后进先出&#xff08;LIFO, Last In First Out&#xff09;的数据结构。它只允许在栈顶进行添加&#xff08;push&#xff09;或删除&#xff08;pop&#xff09;元素的操作。 基本操…...

Java算法之计数排序(Counting Sort)

简介 计数排序是一种线性时间复杂度的排序算法&#xff0c;它不依赖于元素之间的比较&#xff0c;而是通过统计数组中每个元素出现的次数&#xff0c;然后根据这些统计信息对元素进行排序。这种算法特别适用于整数且整数的范围不是非常大时。 算法步骤 找出数组中的最大值。…...

【系统架构设计师-2012年】综合知识-答案及详解

更多内容请见&#xff1a; 备考系统架构设计师-核心总结索引 文章目录 【第1~2题】【第3~4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10~11题】【第12~13题】【第14~19题】【第20~21题】【第22~24题】【第25~26题】【第27~31题】【第32~33题】【第34~36题】【第37…...

webpack4手动搭建Vue项目

小满视频 很多解释使用通义灵码搜的,通义灵码的搜索结果也是有错误的全程使用pnpm包管理工具&#xff0c;和npm的用法基本一样 学习总结 1. 多看看webpack官网 2. webpack的作用&#xff1a;配置一堆东西&#xff0c;达到运行程序的目的 3. 无论什么东西都转成js&#xff0c;…...

Python爬虫所需的技术及其原理(简单易懂)

导言 随着互联网的发展&#xff0c;大量的数据被存储在网络上&#xff0c;而我们需要从中获取有用的信息。Python作为一种功能强大且易于学习的编程语言&#xff0c;被广泛用于网络爬虫的开发。本文将详细介绍Python爬虫所需的技术及其原理&#xff0c;并提供相关的代码案例。…...

FxFactory 8 for Mac 视觉特效插件包安装

Mac分享吧 文章目录 介绍页面效果一、下载软件二、开始安装1、Install安装2、显示软件页面&#xff0c;表示安装成功3、补丁安装 三、注意事项1、若已安装过其他版本&#xff0c;需要使用软件自带的卸载功能进行软件卸载&#xff0c;再安装此版本 安装完成&#xff01;&#x…...

将语义分割的标签转换为实例分割(yolo)的标签

语义分割的标签&#xff08;目标处为255&#xff0c;其余处为0&#xff09; 实例分割的标签&#xff08;yolo.txt&#xff09;,描述边界的多边形顶点的归一化位置 绘制在原图类似蓝色的边框所示。 废话不多说&#xff0c;直接贴代码&#xff1b; import os import cv2 imp…...

QT 遍历ini配置文件

在 Qt 中&#xff0c;处理 INI 配置文件是一项常见任务&#xff0c;通常使用 QSettings 类来读取和写入这些文件。QSettings 提供了一种方便的方式来操作 INI 文件中的配置数据。下面是如何使用 QSettings 遍历和处理 INI 配置文件的示例。 示例代码 假设有一个名为 config.i…...

ecmascript和javascript的区别详细讲解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; ECMAScript 和 JavaScript是紧密相关的术语&#xff0c;但它们有着各自明确的定义和用途。要理解它们的区别&#xff0c;首先需要从它们的起源、发展历史、技术架构以及具体应用领域来分析。以下是对它们的详…...

【Python报错已解决】“ModuleNotFoundError: No module named ‘timm‘”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;当我们尝试导入timm库时&#xff0c;可能会看到以下错误信息。…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

二维FDTD算法仿真

二维FDTD算法仿真&#xff0c;并带完全匹配层&#xff0c;输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...

从实验室到产业:IndexTTS 在六大核心场景的落地实践

一、内容创作&#xff1a;重构数字内容生产范式 在短视频创作领域&#xff0c;IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色&#xff0c;生成的 “各位吴彦祖们大家好” 语音相似度达 97%&#xff0c;单条视频播放量突破百万…...

路由基础-路由表

本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中&#xff0c;往往存在多个不同的IP网段&#xff0c;数据在不同的IP网段之间交互是需要借助三层设备的&#xff0c;这些设备具备路由能力&#xff0c;能够实现数据的跨网段转发。 路由是数据通信网络中最基…...