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

OpenGL Metal Shader 编程:解决图片拉伸变形问题

前面发了一些关于 Shader 编程的文章,有读者反馈太碎片化了,希望这里能整理出来一个系列,方便系统的学习一下 Shader 编程。

由于主流的 Shader 编程网站,如 ShaderToy, gl-transitions 都是基于 GLSL 开发 Shader ,加上 MSL 和 GLSL 语法上差别不大,后面系列文章将以 GLSL 为主来介绍 Shader 编程。

后面 Shader 编程将使用 VSCode + ShaderToy 插件作为编程环境,步骤如下:

  1. 下载安装 VSCode https://code.visualstudio.com/download;

  2. 安装 ShaderToy 插件;

shaderToy.png

  1. 新建以 .frag 为后缀名的文件,复制粘贴本文的代码;

  2. 当前代码,点击鼠标右键,选择 ShaderToy:Show GLSL Preview , 然后就可以愉快地调试特效了。

图片拉伸变形问题


#iChannel0 "https://img-baofun.zhhainiao.com/pcwallpaper_ugc_mobile/static/2ddf8479959f1f3d9f52d0d561d281fe.jpg"void mainImage(out vec4 fragColor, in vec2 fragCoord)
{vec2 uv = fragCoord / iResolution.xy;fragColor = texture2D(iChannel0, uv);
}

我们使用上述代码对纹理通道进行采样,渲染一张图像,可以看到当调整窗口尺寸(iResolution)的时候,图像会因为铺满整个窗口而产生拉伸变形情况。

拉伸.gif

变形的原因这里其实就很好理解了,就是图片宽高比和窗口(视口)的宽高比不同导致的,图像在横轴和纵轴方向产生不同的 resize 强度,最终渲染出来的结果会有拉伸或者压缩的感觉。

iChannelResolution 纹理尺寸

vec3 iChannelResolution[4] 表示各个纹理通道的分辨率(宽度、高度和深度)。通道0对应sampler2D iChannel0,通道1对应sampler2D iChannel1,以此类推。

这个 ShaderToy 全局变量单独拿出来讲,因为纹理尺寸在实际开发中会频繁用到,主要用来解决图像的拉伸问题。

拉伸不变形 2.gif

有了纹理尺寸,我们就可以在窗口中找一块宽高比和图像一样的区域,只让图像渲染到这块区域,从而避免图像拉伸。


#iChannel0 "https://img-baofun.zhhainiao.com/pcwallpaper_ugc_mobile/static/2ddf8479959f1f3d9f52d0d561d281fe.jpg"void mainImage(out vec4 fragColor, in vec2 fragCoord)
{vec2 uv = fragCoord / iResolution.xy;//纹理尺寸vec2 imgSize = iChannelResolution[0].xy;//窗口尺寸vec2 viewPort = iResolution.xy;//图像宽高比float imgRatio = imgSize.x / imgSize.y;//窗口宽高比float screenRatio = viewPort.x / viewPort.y;//resizeTarget 表示窗口中与图像宽高比保持一致的区域大小vec2 resizeTarget = viewPort;//窗口中与图像宽高比保持一致的区域的位置vec2 startPos = vec2(0.0);//与窗口的一个边对齐,使图像渲染在窗口中央if(imgRatio > screenRatio) {resizeTarget.x = viewPort.x;resizeTarget.y = resizeTarget.x / imgRatio;startPos.y = (viewPort.y - resizeTarget.y) / 2.0;} else {resizeTarget.y = viewPort.y;resizeTarget.x = resizeTarget.y * imgRatio;startPos.x = (viewPort.x - resizeTarget.x) / 2.0;}//窗口中与图像宽高比保持一致的区域内渲染图像if(fragCoord.x >= startPos.x && fragCoord.x <= startPos.x + resizeTarget.x && fragCoord.y >= startPos.y && fragCoord.y <= startPos.y + resizeTarget.y) {uv.x = (fragCoord.x - startPos.x) / resizeTarget.x;uv.y = (fragCoord.y - startPos.y) / resizeTarget.y;fragColor = texture2D(iChannel0, uv);} else {fragColor = vec4(0.0);}}

后续安排

后面 OpenGL & Metal Shader 编程系列文章大致安排:

  1. ShaderToy 内置全局变量

  2. 重要的内置函数

  3. 基本图形

  4. 距离场

  5. 噪声函数

  6. 基础特效…

  7. 转场特效…

  8. 高阶特效…

联系交流

技术交流/获取视频教程可以添加我的微信:Byte-Flow

联系我

http://www.lryc.cn/news/97407.html

相关文章:

  • [SQL挖掘机] - 字符串函数 - concat
  • Rust之所有权
  • RabbitMQ帮助类的封装
  • mac 移动硬盘未正常退出,再次链接无法读取(显示)
  • 短视频账号矩阵系统源码开发部署路径
  • 前端 | ( 十一)CSS3简介及基本语法(上) | 尚硅谷前端html+css零基础教程2023最新
  • Kafka入门到起飞系列 - 副本机制,什么是副本因子呢?
  • 2023年基准Kubernetes报告:6个K8s可靠性失误
  • 程序员面试系列,k8s常见面试题
  • docker版jxTMS使用指南:站点的调整
  • element ui input 深层循环v-model绑定默认数据删除不了的情况
  • GBDT的参数空间与超参数优化
  • 多线程练习——抽奖箱
  • RK3399平台开发系列讲解(内核调试篇)Valgrind 内存调试与性能分析
  • Windows 11的最新人工智能应用Windows Copilot面世!
  • Mac 预览(Preview)丢失PDF标注恢复
  • 4.5. 方法的四种类型
  • 四旋翼无人机使用教程
  • 优化 PHP 数据库查询性能
  • vue 使用stompjs websocket连接rabbitmq
  • com.android.ide.common.signing.KeytoolException:
  • leetcode 1870. Minimum Speed to Arrive on Time(准时到达的最小速度)
  • 本地非文字资源无法加载
  • Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购
  • 万向节死锁
  • 大数据课程D1——hadoop的初识
  • xml命名空间
  • 七、Kafka源码分析之网络通信
  • WEB安全测试通常要考虑的测试点
  • 关于uni.createInnerAudioContext()的duration音频长度获取不到问题