这是一个实用且足够高性能的着色器,可以在移动设备上进行模糊处理吗?

2024-01-12

我正在尝试使用 GLSL 着色器在移动设备上的游戏中实现模糊效果。我以前没有任何编写着色器的经验。我不明白我的着色器是否足够好。其实我已经从教程中复制了GLSL代码,我不知道这个教程是为了生动的演示还是也可以在实践中使用。这是使用高斯权重的两通道模糊着色器的代码(http://www.cocos2d-x.org/wiki/User_Tutorial-RenderTexture_Plus_Blur http://www.cocos2d-x.org/wiki/User_Tutorial-RenderTexture_Plus_Blur):

#ifdef GL_ES                                                                      
precision mediump float;
#endif                                                                            

varying vec4 v_fragmentColor;                                                     
varying vec2 v_texCoord;                                                          

uniform vec2 pixelSize;
uniform vec2 direction;
uniform int radius;
uniform float weights[64];

void main() 
{
    gl_FragColor = texture2D(CC_Texture0, v_texCoord)*weights[0];
    for (int i = 1; i < radius; i++) {
        vec2 offset = vec2(float(i)*pixelSize.x*direction.x, float(i)*pixelSize.y*direction.y);
        gl_FragColor += texture2D(CC_Texture0, v_texCoord + offset)*weights[i];
        gl_FragColor += texture2D(CC_Texture0, v_texCoord - offset)*weights[i];
    }
}   

我在每次帧更新时运行此着色器(每秒 60 次),而我的游戏帧率在 iPhone 5S(不错的设备)上仅一次通过就下降至 22 FPS。我认为这非常非常奇怪。似乎没有太多的指导。为什么这个这么重?

附:模糊半径为 50,步长为 1。


着色器很重的主要原因:

1:这两个计算:v_texCoord + offset and v_texCoord - offset。由于 uv 坐标是在片段着色器中计算的,因此必须当场从内存加载纹理数据,从而导致缓存未命中。

什么是依赖纹理读取? https://stackoverflow.com/questions/1054096/what-is-a-dependent-texture-read

2: radius太大了。

如何让它更快/更好:

1:在顶点着色器中尽可能多地计算。理想情况下,如果您在顶点着色器中计算所有 UV,GPU 可以在调用片段着色器之前移动缓存中的纹理内存,从而显着提高性能。

2:减少Radius可以容纳8-16人texture2D来电。这可能不会给您期望的结果,为了解决这个问题,您可以使用 2 个纹理,将纹理 A 模糊到 B 中,然后再次将 B 模糊到纹理 A 中,依此类推,根据需要进行模糊处理。这将给出非常好的结果,我记得 crisys 1 使用它进行运动模糊,但我找不到论文。

3:消除那 64 个制服,将所有数据硬编码在着色器中。我知道这不太好,但你会获得一些额外的性能。

4:如果仔细计算 UV 坐标,您可以充分利用纹理插值。基本上不会对中心的像素进行采样,总是在像素之间进行采样,硬件会执行此操作并取附近 4 个像素的平均值:

https://en.wikipedia.org/wiki/Bilinear_filtering https://en.wikipedia.org/wiki/Bilinear_filtering

5:这一行:precision mediump float;一切都必须如此吗mediump?我建议删除它并进行一些测试lowp尽可能多地进行。

编辑: 对于您的着色器,这是您需要执行的操作的简化版本:

顶点着色器:

attribute highp vec4 Position;
attribute mediump vec2 texture0UV;

varying mediump vec2 v_texCoord0;
varying mediump vec2 v_texCoord1;
varying mediump vec2 v_texCoord2;
varying mediump vec2 v_texCoord3;
varying mediump vec2 v_texCoord5;

uniform mediump vec2 texture_size;

void main() 
{
    gl_Position = Position;
    vec2 pixel_size = vec2(1.0) / texture_size;
    vec2 offset;


    v_texCoord0 = texture0UV;
    v_texCoord1 = texture0UV + vec2(-1.0,0.0) / texture_size + pixel_size * 0.5;
    v_texCoord2 = texture0UV + vec2(0.0,-1.0) / texture_size + pixel_size * 0.5;
    v_texCoord3 = texture0UV + vec2(1.0,0.0) / texture_size  - pixel_size * 0.5;
    v_texCoord4 = texture0UV + vec2(0.0,1.0) / texture_size  - pixel_size * 0.5;
}

最后一次操作pixel_size * 0.5需要最大限度地利用线性插值。在此示例中,您选择的采样位置很简单,但有关如何选择采样位置的完整讨论超出了本问题的范围。

片段着色器:

varying mediump vec2 v_texCoord0;
varying mediump vec2 v_texCoord1;
varying mediump vec2 v_texCoord2;
varying mediump vec2 v_texCoord3;
varying mediump vec2 v_texCoord5;

uniform lowp sampler2D CC_Texture0;

void main() 
{
    mediump vec4 final_color = vec4(0.0);

    final_color += texture2D(CC_Texture0,v_texCoord0);
    final_color += texture2D(CC_Texture0,v_texCoord1);
    final_color += texture2D(CC_Texture0,v_texCoord2);
    final_color += texture2D(CC_Texture0,v_texCoord3);
    final_color += texture2D(CC_Texture0,v_texCoord4);

    gl_FragColor = final_color / 5.0;//weights have to go, use fixed values instead, in this case it's 1/5 for each sample
}

为了让效果看起来不错,您需要多次模糊纹理,即使您模糊纹理 2 次,您也应该看到明显的差异。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这是一个实用且足够高性能的着色器,可以在移动设备上进行模糊处理吗? 的相关文章

  • InvalidOperationException - 对象当前正在其他地方使用 - 红十字

    我有一个 C 桌面应用程序 其中我连续创建的一个线程从源 实际上是一台数码相机 获取图像并将其放在 GUI 中的面板 panel Image img 上 这必须是另一个线程 如它是控件的代码隐藏 该应用程序可以工作 但在某些机器上 我会在随
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • 如何在c++中读取pcap文件来获取数据包信息?

    我想用 C 编写一个程序来读取 pcap 文件并获取数据包的信息 例如 len sourc ip flags 等 现在我找到了如下代码 我认为它会帮助我获取信息 但是我有一些疑问 首先我想知道应该将哪个库添加到我的程序中 然后什么是 pca
  • ClickOnce 应用程序错误:部署和应用程序没有匹配的安全区域

    我在 IE 中使用 FireFox 和 Chrome 的 ClickOnce 应用程序时遇到问题 它工作正常 异常的详细信息是 PLATFORM VERSION INFO Windows 6 1 7600 0 Win32NT Common
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 单个对象的 Monogame XNA 变换矩阵?

    我读过一些解释 XNA Monogame 变换矩阵的教程 问题是这些矩阵应用于 SpriteBatch Begin matrix 这意味着所有 Draw 代码都将被转换 如何将变换矩阵应用于单个可绘制对象 就我而言 我想转换滚动背景 使其自
  • 为什么 Google 测试会出现段错误?

    我是 Google Test 的新手 正在尝试提供的示例 我的问题是 当我引入失败并设置GTEST BREAK ON FAILURE 1 或使用命令行选项 GTest 将出现段错误 我正在考虑这个例子 https code google c
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • 由 IHttpClientFactory 注入时模拟 HttpClient 处理程序

    我创建了一个自定义库 它会自动为依赖于特定服务的 Polly 策略设置HttpClient 这是使用以下方法完成的IServiceCollection扩展方法和类型化客户端方法 一个简化的例子 public static IHttpClie
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • 等待进程释放文件

    我如何等待文件空闲以便ss Save 可以用新的覆盖它吗 如果我紧密地运行两次 左右 我会得到一个generic GDI error
  • Cmake 链接共享库:包含库中的头文件时“没有这样的文件或目录”

    我正在学习使用 CMake 构建库 构建库的代码结构如下 include Test hpp ITest hpp interface src Test cpp ITest cpp 在 CMakeLists txt 中 我用来构建库的句子是 f
  • 不同类型指针之间的减法[重复]

    这个问题在这里已经有答案了 我试图找到两个变量之间的内存距离 具体来说 我需要找到 char 数组和 int 之间的距离 char data 5 int a 0 printf p n p n data 5 a long int distan
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看

随机推荐

  • 使用 urllib 发出 post 请求

    我正在尝试向 API 提供商提出请求 curl https api infermedica com dev parse X POST H App Id 4c177c H App Key 6852599182ba85d70066986ca2b
  • 如何将第三方 javascript 库与 ionic4 和电容器一起使用?

    使用 Ionic 4 Angular 应用程序和 Capacitor 安装第三方 javascript 库的正确方法是什么 我尝试安装克鲁克图书馆 https github com jackedgson crunker如下 npm inst
  • Angular 2 中不同页面的多种布局

    我有一个登录页面 只有 2 个输入 无页眉 无页脚 无侧边栏 当用户登录时 他应该导航到带有页眉 页脚和右侧导航栏的页面 内页唯一改变的是右侧内容 import Component from angular core import View
  • Android Studio 中相对布局问题中按钮顶部的进度条

    好吧 这是一个奇怪的问题 我希望有人能向我解释一下 我有一个自定义按钮布局 它创建一个按钮 按钮中间有一个圆形进度条 我的 XML 代码如下 然而我无法解决的是ProgressBar似乎出现在按钮后面 如果我将按钮背景设置为透明以外的任何内
  • Spring Boot 组件扫描不起作用

    我创建了一个示例 Spring Boot 应用程序 当服务类全部位于一个包中时 该应用程序运行得非常好 但如果服务类引用不同包中的另一个服务类 那么我会收到 BeanCreationException 应用程序的代码如下 主程序 java
  • GLEW:Apple Mach-O 链接器 (Id) 错误

    我试图在我的 Xcode 项目中使用 glew 但我得到了这个 Apple Mach O Linker Id Error Undefined symbols for architecture x86 64 我正在使用从他们下载的最新版本的g
  • Protocol buffers 从原始消息中检测类型

    是否可以检测原始协议缓冲区消息的类型 以字节 为单位 我遇到的情况是端点可以接收不同的消息 并且我需要能够在反序列化之前检测到类型 我正在使用 protobuf net 您无法单独检测类型 因为 protobuf 规范不会为此向流添加任何数
  • 如何使用presto查询hive数据

    我刚刚安装了 presto 当我使用 presto cli 查询 hive 数据时 出现以下错误 presto server node6 8080 catalog hive schema default presto default gt
  • Xcode 9 - 无法附加到 pid 进行框架单元测试

    使用时间机器从一台 Mac 迁移到另一台 Mac 后 我收到以下错误 无法附加到 pid 确保 项目标题 尚未运行 并且 系统用户名 有调试权限 仅当运行 任何 框架项目的单元测试时才会发生该错误 在模拟器和设备上运行应用程序效果很好 为应
  • 在 C# 中从 LINQ 提取 SQL 列扩展属性

    我有一个 SQL 表 每列都有扩展属性 有没有办法使用 Linq2SQL 从 C 中的 LINQ 访问这些 像 MS Description 之类的东西 不 据我所知 您可以编写一个与数据库中的存储进行对话的 SP 获取数据库对象名称和列名
  • 找不到 Storm 日志查看器页面

    我可以在多租户集群中提交拓扑作业 作业正在运行 但是 日志查看器页面不可用 有什么办法可以解决这个问题吗 在单击之前您需要启动日志查看器topology port查看日志查看器 要启动日志查看器 请运行 storm logviewer和你跑
  • 从二维列表中获取唯一元素

    我有一个二维列表 我像这样创建 Z1 0 for x in range 3 for y in range 4 然后我继续填充这个列表 这样Z1看起来像这样 1 2 3 4 5 6 2 3 1 2 5 1 我需要提取unique 1x3要点Z
  • 更改ios8扩展导航栏颜色

    我正在开发 iOS8 应用程序扩展 照片编辑扩展 我尝试过这些方法来更新导航栏颜色 但失败了 UINavigationBar appearance setBarTintColor UIColor yellowColor UINavigati
  • 如何用值向量填充索引矩阵

    我有一个矩阵 m idx 其中包含我想要索引的向量的位置元素 gt m idx 1 2 3 4 5 1 1 2 3 4 5 2 3 4 5 6 7 3 5 6 7 8 9 假设 x 是我的向量 x lt c 9 3 2 5 3 2 4 8
  • 2D 物理引擎:弹跳球与非弹性碰撞不会停止

    我用 Java 创建了一个简单的 2d 物理引擎 它使用圆形射弹和直墙 目前 对于每一帧 每个射弹的位置都会提前velocity 1 fps 之后速度每帧更新一次 碰撞检测使用先前位置和当前位置以点斜率形式定义一条线 检查该线是否与墙壁相交
  • 每 N 行重复一次 Excel 公式

    我正在尝试在 Excel 中添加一个重复公式 该公式将对每个科目的另一列 分数 中的一系列值进行求和 以获得每个科目的总分 我添加了以下公式 该公式似乎正确地合计了值 SUM 偏移 AO 2 ROW 424 424 0 424 1 You
  • 如何更改本机反应中警报的颜色

    如何在 React Native 中更改警报框的背景颜色 字体大小 我在单击按钮后发出警报 我不知道如何设计这个样式 谢谢您的帮助 Alert alert Plate Plate has been sent for printing tex
  • Elasticsearch 7.2.0:尚未发现或选举主节点,选举至少需要 X 个节点

    我正在尝试自动化 Kubernetes 集群中 Elasticsearch 节点的水平扩展和缩小过程 最初 我在 Kubernetes 集群上部署了一个 Elasticsearch 集群 3 个主节点 3 个数据节点和 3 个摄取节点 在哪
  • htaccess 将不带 .php 扩展名的 URL 重写到文件

    我有一个使用 osCommerce 的网站 所有页面都可以直接访问http www example com pagename php 但现在我想调整 htaccess 文件 以便它可以支持http www example com usern
  • 这是一个实用且足够高性能的着色器,可以在移动设备上进行模糊处理吗?

    我正在尝试使用 GLSL 着色器在移动设备上的游戏中实现模糊效果 我以前没有任何编写着色器的经验 我不明白我的着色器是否足够好 其实我已经从教程中复制了GLSL代码 我不知道这个教程是为了生动的演示还是也可以在实践中使用 这是使用高斯权重的