shader编程-二维空间中使用矩阵实现物体的旋转、缩放、平移变换

  • 1. 变换前物体的绘制
  • 2. 物体旋转的实现
  • 3. 物体缩放的实现
  • 4. 物体平移的实现
  • 5. 平移与缩放另外一种实现方式
  • 6. 所有示例代码

1. 变换前物体的绘制

在进行变换操前先绘制出要操作的物体,我们就简单的绘制一个矩形来代表,利用之前的绘制矩形的代码稍作修改,之前用的是step函数,现在调整为smoothstep函数,因为旋转时使用step函数绘制的矩形边缘会出现锯齿,具体如下

float box(vec3 st){float right = 0.15;float top = 0.1;float blur = 0.002;//边缘模糊系数//通过右上角绘制原点对称的四边形vec2 bl = 1.0-smoothstep(vec2(right,top)-blur,vec2(right,top)+blur,abs(st.xy));float pct = bl.x * bl.y;return pct;
}

绘制的结果如下,一个小矩形出现在绘制区域中央

2. 物体旋转的实现

我们使用矩阵来实现物体的旋转,先来看看齐次坐标下的旋转矩阵长什么样

上面的矩阵用于二维平面下对物体进行旋转变换,旋转矩阵的相关知识,请参照这篇文章图形学中的基本变换

接下来看看获取旋转矩阵函数的代码

 mat3 rotate2d(float _angle){float angle = radians(_angle);//角度转为弧度return mat3(cos(angle),-sin(angle),0.0,sin(angle),cos(angle),0.0,0.0,0.0,1.0);}

调用的时候需要注意一下,齐次坐标下返回的旋转矩阵是一个三维矩阵,所以先将屏幕坐标转为三维坐标,以匹配旋转矩阵,与旋转矩阵相乘后相当于将整个屏幕坐标旋转了,接着绘图,绘出的图就带旋转效果了,具体参照如下代码

void main( void ) {//窗口坐标调整为[-1,1],坐标原点在屏幕中心vec2 _st = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;vec3 line_color = vec3(1.0,1.0,0.0);vec3 color = vec3(0.6);//背景色float pct = 0.0;//将屏幕坐标转为三维坐标,使之在和矩阵相乘时相匹配vec3 st = vec3(_st,1.0);//使用旋转矩阵使矩形顺时针旋转10度st *= rotate2d(10.0);pct = box(st);color = mix(color,line_color,pct);gl_FragColor = vec4(color, 1);
}

看看运行结果,矩形在原来的基础上顺时针旋转了10度

如果想逆时针旋转10度,只需要在参数前添加个负号

st *= rotate2d(-10.0);

如果你想让它不停旋转,需要用到u_time变量,之所以乘以30.0,是为了让物体旋转的更快一些

st *= rotate2d(u_time*30.0);

3. 物体缩放的实现

同样先来看看齐次坐标下缩放矩阵的模样

该矩阵相关知识还是参照这篇文章图形学中的基本变换

接着我们编写返回缩放矩阵的函数,如下

mat3 scale2d(vec2 scale){//缩放矩阵作用于坐标系,所以放大和缩小刚好相反,为了使用习惯,缩放参数取倒数return mat3(1.0/scale.x,0.0,0.0,0.0,1.0/scale.y,0.0,0.0,0.0,1.0);
}

绘制物体前,将屏幕坐标与该矩阵相乘

st *= scale2d(vec2(2.0,4.0));

执行上面的代码物体x轴方向放大2倍,y轴方向放大4倍,结果如下

4. 物体平移的实现

下图是齐次坐标下平移矩阵

该矩阵相关知识还是参照这篇文章图形学中的基本变换

开始编写返回平移矩阵的函数,如下

mat3 translation2d(vec2 translate){//平移矩阵作用于坐标系,所以平移的方向相反,为了使用习惯,缩放参数取负return mat3(1.0,0.0,-translate.x,0.0,1.0,-translate.y,0.0,0.0,1.0);
}

绘图前屏幕坐标与平移坐标相乘

st *= translation2d(vec2(0.2,0.4));

执行结果如下图,与原物体相比,在x轴方向平移0.2,y轴方向平移0.4

如果将代码调整成下面的代码,则物体沿着y轴像弹簧一样做上下往复运动

st *= translation2d(vec2(0.0,sin(u_time)*0.5));

如果替换为下面代码,则物体会沿着半径为0.5的圆环上做环形运动

st *= translation2d(vec2(cos(u_time)*0.5,sin(u_time)*0.5));

至此,如果你已经掌握物体的基本变换就,其实各种变换是可以叠加的,只需要不断地乘上变换矩阵,例如让物体既自己旋转,又通过平移矩阵实现环形运动,可使用以下代码

st *= rotate2d(u_time*30.0);
st *= translation2d(vec2(cos(u_time)*0.5,sin(u_time)*0.5));

5. 平移与缩放另外一种实现方式

平移与缩放可以通过另外一种不使用矩阵的方式实现,原理就是改变屏幕坐标,物体则以相反的变换变化,例如将屏幕坐标乘以2,相当于屏幕坐标放大两倍,而绘制物体时大小不变,则物体看起来像缩小为原来的一半,如果你对屏幕坐标的x轴减0.5个单位,绘制的结果是物体向右移动0.5个单位
一些简单的平移与缩放示例代码

//非矩阵的放大缩小方式
//st *=3.0;//屏幕坐标放大3倍,相当于物体缩小3倍
//st /=3.0;//屏幕坐标缩小3倍,相当于物体放大3倍//非矩阵的平移方式
//st.x -=0.2;//物体向右移0.2个单位
//st -=0.4;//物体向右向上移0.4个单位
//st.x +=0.3;//物体向左移0.3个单位

6. 所有示例代码

<body><div id="container"></div><script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script><script>var container;var camera, scene, renderer;var uniforms;var vertexShader = `void main() {gl_Position = vec4( position, 1.0 );} `var fragmentShader = `#ifdef GL_ESprecision mediump float;#define sat(x) clamp(x, 0.0, 1.0)#endifuniform float u_time;uniform vec2 u_mouse;uniform vec2 u_resolution;mat3 rotate2d(float _angle){float angle = radians(_angle);//角度转为弧度return mat3(cos(angle),-sin(angle),0.0,sin(angle),cos(angle),0.0,0.0,0.0,1.0);}mat3 scale2d(vec2 scale){//缩放矩阵作用于坐标系,所以放大和缩小刚好相反,为了使用习惯,缩放参数取倒数return mat3(1.0/scale.x,0.0,0.0,0.0,1.0/scale.y,0.0,0.0,0.0,1.0);}mat3 translation2d(vec2 translate){//平移矩阵作用于坐标系,所以平移的方向相反,为了使用习惯,缩放参数取负return mat3(1.0,0.0,-translate.x,0.0,1.0,-translate.y,0.0,0.0,1.0);}float box(vec3 st){float right = 0.15;float top = 0.1;float blur = 0.002;//边缘模糊系数//通过右上角绘制原点对称的四边形vec2 bl = 1.0-smoothstep(vec2(right,top)-blur,vec2(right,top)+blur,abs(st.xy));float pct = bl.x * bl.y;return pct;}void main( void ) {//窗口坐标调整为[-1,1],坐标原点在屏幕中心vec2 _st = (gl_FragCoord.xy * 2. - u_resolution) / u_resolution.y;//窗口坐标调整为[0,1],坐标原点在屏幕左下角//vec2 st = gl_FragCoord.xy/u_resolution;vec3 line_color = vec3(1.0,1.0,0.0);vec3 color = vec3(0.6);//背景色float pct = 0.0;//将屏幕坐标转为三维坐标,使之在和矩阵相乘时相匹配vec3 st = vec3(_st,1.0);//使用旋转矩阵使矩形顺时针旋转10度//st *= rotate2d(10.0);//st *= rotate2d(u_time*30.0);//缩放//st *= scale2d(vec2(2.0,4.0));//平移//st *= translation2d(vec2(0.2,0.4)); //st *= translation2d(vec2(0.0,sin(u_time)*0.5));//st *= translation2d(vec2(cos(u_time)*0.5,sin(u_time)*0.5));//非矩阵的放大缩小方式//st *=3.0;//屏幕坐标放大3倍,相当于物体缩小3倍//st /=3.0;//屏幕坐标缩小3倍,相当于物体放大3倍//非矩阵的平移方式//st.x -=0.2;//物体向右移0.2个单位//st -=0.4;//物体向右向上移0.4个单位//st.x +=0.3;//物体向左移0.3个单位pct = box(st);color = mix(color,line_color,pct);gl_FragColor = vec4(color, 1);}`init();animate();function init() {container = document.getElementById('container');camera = new THREE.Camera();camera.position.z = 1;scene = new THREE.Scene();var geometry = new THREE.PlaneBufferGeometry(2, 2);uniforms = {u_time: {type: "f",value: 1.0},u_resolution: {type: "v2",value: new THREE.Vector2()},u_mouse: {type: "v2",value: new THREE.Vector2()}};var material = new THREE.ShaderMaterial({uniforms: uniforms,vertexShader: vertexShader,fragmentShader: fragmentShader});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);renderer = new THREE.WebGLRenderer();//renderer.setPixelRatio(window.devicePixelRatio);container.appendChild(renderer.domElement);onWindowResize();window.addEventListener('resize', onWindowResize, false);document.onmousemove = function (e) {uniforms.u_mouse.value.x = e.pageXuniforms.u_mouse.value.y = e.pageY}}function onWindowResize(event) {renderer.setSize(800, 800);uniforms.u_resolution.value.x = renderer.domElement.width;uniforms.u_resolution.value.y = renderer.domElement.height;}function animate() {requestAnimationFrame(animate);render();}function render() {uniforms.u_time.value += 0.02;renderer.render(scene, camera);}</script>
</body>

shader编程-二维空间中使用矩阵实现物体的旋转、缩放、平移变换(WebGL-Shader开发基础03)相关推荐

  1. 图像中的一条直线在旋转缩放过程中会有分段现象,或产生分段节点

    图像中的一条直线在旋转缩放过程中会有分段现象. 图像在Windows照片查看器中打开.显示. 使用滚轮放大缩小. 原来的一条直线会分段. 图像旋转方式:16相位(33端).32 原图: 经旋转45,放 ...

  2. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...

  3. 【Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...

  4. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 第一个Shader的书写...

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...

  5. Unity Hololens开发控制物体移动旋转缩放

    先说在unity中的按键操作 环顾四周:鼠标右键+移动鼠标 移动物体(右手):空格+移动鼠标+鼠标左键 移动物体(左手):shift+移动鼠标+鼠标左键 右手旋转:ctrl+空格+移动鼠标+鼠标左键 ...

  6. unity3d鼠标控制物体 移动 旋转 缩放

    需求:制作一个鼠标中键移动缩放和鼠标右键旋转的功能(鼠标右键旋转可以自行改成鼠标左键旋转) 效果图: 1.新建一个名为Target的立方体cube 2.新建一个材质球 Yellow颜色的并挂载到Tar ...

  7. html文字旋转以后变形,关于css:CSS3中的变形处理transform功能旋转缩放倾斜移动

    1 transform属性 在CSS3中,能够利用transform性能实现文字或图像的旋转.缩放.歪斜.挪动这4中类型的变形解决. (1)浏览器反对 到目前为止:Safari3.1以上.Chrome ...

  8. 鼠标控制物体移动旋转缩放

    给相机添上o( ̄︶ ̄)o using System.Collections; using System.Collections.Generic; using UnityEngine;public cl ...

  9. 对《Python核心编程》中“第一个Python程序”的改进

    概述: 本程序主要是模仿<Python核心编程>中3.6节--第一个Python程序,并在其基础上做了一些小的改进,而改进的要求则是来源于第三章的课后练习题. 本篇博客的一个核心问题就是在 ...

最新文章

  1. [architecture]-AXI/APB/AHB/ACE的介绍
  2. 【放置奇兵】踩坑记录( 白字、红字、黄字)tips 小技巧
  3. PHP——PHP读取MySQL数据库中文乱码解决方案
  4. shell 和 || 的短路使用
  5. java 存储空间_Java中的存储空间类型
  6. 为什么python 为什么没有接口_python做接口测试的必要性
  7. eeg数据集_运动想象,情绪识别等公开数据集汇总
  8. CentOS 6.5高可用集群LVS+Keepalived
  9. idea+SpringBoot+Mybatis+Mysql环境搭建
  10. 1,3-丙二硫醇行业调研报告 - 市场现状分析与发展前景预测
  11. 重新想象 Windows 8.1 Store Apps (91) - 后台任务的新特性: 下载和上传的新特性, 程序启动前预下载网络资源, 后台任务的其它新特性...
  12. 小程序开发 js里面array操作的方法列表。
  13. 数据损坏了,怎么找回来?用超融合备份一体机啊
  14. MySQL学习笔记:一道group by+group_concat解决的小问题
  15. android 属性翻牌动画,如何在Android中利用TextSwitcher实现一个文字上下翻牌效果
  16. 一起学习R软件吧——R软件的使用
  17. 4.3 数值分析: 简单迭代法的构造和收敛条件
  18. 最短路径算法之Dijkstra算法(java实现)
  19. html去除背景颜色怎么设置,去掉背景颜色的六种情况
  20. Hive学习(待续)

热门文章

  1. 什么是MIMO-OFDM技术
  2. 伽马分布,指数分布,泊松分布的关系 -转自简书
  3. python模板公式代码替换,Python - 字符串模板的安全替换(safe_substitute) 详解
  4. 突击Mercurial SCM(HG)2---当前状态
  5. android 界面布局-各个布局的属性介绍,你值得拥有
  6. 安装国外浏览器的好处
  7. Django中的app
  8. vscode java环境_VSCode中Java开发环境的配置方法
  9. 一致性hash算法虚拟节点_一致性hash和虚拟节点
  10. 从微信「拍一拍」,我想到了那些神奇的一行代码功能(文末福利)