(三)GL 空间变换
文章目录
- 1.前言
- 2.GL类坐标变换
- 2.1 世界坐标系
- 2.2 局部坐标系
- 2.3 屏幕坐标系
- 2.4 正交坐标系
- 2.5 视口分离
- 3.完整代码
1.前言
采用GL类以及Graphics类进行绘制图形时,都需要用到坐标变换。这跟采用图形学接口进行绘制时相同。以一个球为例,如果在坐标原点处绘制,球心坐标为0。如果在其他位置绘制,球心坐标不为0,此时球面顶点坐标需要重新计算。如果采用矩阵变换(坐标变换),将坐标原点移动到球心所在的位置,则球心仍在原点位置,球面坐标保持不变。所以我们在绘制一个图形时,先进行坐标变换,然后再绘制,绘制结束后再恢复到原来坐标系(即世界坐标系),然后再坐标变换绘制其他图形,然后再恢复到世界坐标系。
2.GL类坐标变换
此节主要针对GL类几个加载坐标系的方法来进行说明,如LoadPixelMatrix、MultMatrix等。
2.1 世界坐标系
默认为世界坐标系,如下代码为在世界坐标系下绘制正多边形。此时移动camera,图像会移动。因为图像的坐标与camera坐标无关系。
public int circleRadius = 3;public int circleCount = 6;public int zValue = 0;private void DrawCircleSurface(){float angleDelta = 2 * Mathf.PI / circleCount;GL.Begin(GL.TRIANGLES);GL.Color(Color.yellow);for (int i = 0; i < circleCount; i++){float angle = angleDelta * i;float angleNext = angle + angleDelta;GL.Vertex3(0, 0, zValue);GL.Vertex3(Mathf.Cos(angle) * circleRadius, Mathf.Sin(angle) * circleRadius, zValue);GL.Vertex3(Mathf.Cos(angleNext) * circleRadius, Mathf.Sin(angleNext) * circleRadius, zValue);}GL.End();}`在这里插入代码片`
2.2 局部坐标系
如果我们让图像变成某一个游戏物体的子物体(如camera),可以采用GL.MultMatrix方法。首先通过transform.localToWorldMatrix获取局部坐标到世界坐标的变换矩阵,然后通过GL.MultMatrix加载进来就可以。此时我们进行绘制时,计算的坐标都为局部坐标,最终数据会通过坐标转换为世界坐标系下结果,代码如下。如果此时再移动camera,图像则跟随camera移动。
private void DrawCircleSurfaceLocal(){GL.PushMatrix();GL.MultMatrix(transform.localToWorldMatrix);DrawCircleSurface();GL.PopMatrix();}
2.3 屏幕坐标系
可以通过GL.LoadPixelMatrix将图像直接绘制到屏幕上,此方法有两个重载,对应绘制到当前屏幕上和绘制到指定大小像素上。如果指定大小像素与屏幕相同,则即为绘制到当前屏幕大小。但是此时图像坐标是以像素为大小的,且z值坐标为0.。而且屏幕坐标没有负值,所以以本例正多边形为例,由于原点在0位置,所以屏幕只能显示四分之一图像。
private void DrawCircleSurfaceScreen(){//circleRadius = 1000; 以像素为单位GL.PushMatrix();//GL.LoadPixelMatrix();GL.LoadPixelMatrix(0,screenSize.x,0,screenSize.y);DrawCircleSurface();GL.PopMatrix();}
当screenSize的x与y值和屏幕分辨率相同时,与GL.LoadPixelMatrix()的效果一致。
2.4 正交坐标系
采用GL.LoadOrtho()方法可以将图像直接绘制到屏幕上,此时是正交视图,大小为1,所以坐标系数值均要小于等于1.。同样坐标值没有负值。
private void DrawCircleSurfaceOrtho(){//circleRadius = 1; 最大值为1GL.PushMatrix();GL.LoadOrtho();DrawCircleSurface();GL.PopMatrix();}
2.5 视口分离
通过GL.Viewport方法可以实现绘制在局部视口内,如下所示:
private void DrawCircleSurfaceViewport(){GL.PushMatrix();GL.LoadPixelMatrix();GL.Viewport(new Rect(0, 0, Screen.width / 2, Screen.height / 2));DrawCircleSurface();GL.PopMatrix();}
注意:如果坐标系采用的正交坐标系,即采用GL.LoadOrtho()方法,则视口的最大值为1,此时 GL.Viewport(new Rect(0, 0, 1.0f / 2, 1.0f / 2));
3.完整代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Graphics03GLMatrix : MonoBehaviour
{public enum SpaceType{WORLD,LOCAL,SCREEN_NORMAL,SCREEN,VIEWPORT}public SpaceType type = SpaceType.WORLD;public int circleRadius = 3;public int circleCount = 6;public int zValue = 0;public Vector2 screenSize = Vector2.zero;private void OnRenderObject(){SetMaterialPass();switch (type){case SpaceType.WORLD:DrawCircleSurface();break;case SpaceType.LOCAL:DrawCircleSurfaceLocal();break;case SpaceType.SCREEN_NORMAL:DrawCircleSurfaceOrtho();break;case SpaceType.SCREEN:DrawCircleSurfaceScreen();break;case SpaceType.VIEWPORT:DrawCircleSurfaceViewport();break;}}private Material glMat;private void SetMaterialPass(){if (glMat == null){glMat = new Material(Shader.Find("Hidden/Internal-Colored"));}glMat.SetPass(0);}private void DrawCircleSurface(){float angleDelta = 2 * Mathf.PI / circleCount;GL.Begin(GL.TRIANGLES);GL.Color(Color.yellow);for (int i = 0; i < circleCount; i++){float angle = angleDelta * i;float angleNext = angle + angleDelta;GL.Vertex3(0, 0, zValue);GL.Vertex3(Mathf.Cos(angle) * circleRadius, Mathf.Sin(angle) * circleRadius, zValue);GL.Vertex3(Mathf.Cos(angleNext) * circleRadius, Mathf.Sin(angleNext) * circleRadius, zValue);}GL.End();}private void DrawCircleSurfaceLocal(){GL.PushMatrix();GL.MultMatrix(transform.localToWorldMatrix);DrawCircleSurface();GL.PopMatrix();}private void DrawCircleSurfaceOrtho(){//circleRadius = 1; 最大值为1GL.PushMatrix();GL.LoadOrtho();DrawCircleSurface();GL.PopMatrix();}private void DrawCircleSurfaceScreen(){//circleRadius = 1000; 以像素为单位GL.PushMatrix();//GL.LoadPixelMatrix();GL.LoadPixelMatrix(0,screenSize.x,0,screenSize.y);DrawCircleSurface();GL.PopMatrix();}private void DrawCircleSurfaceViewport(){GL.PushMatrix();GL.LoadPixelMatrix();GL.Viewport(new Rect(0, 0, Screen.width / 2, Screen.height / 2));DrawCircleSurface();GL.PopMatrix();}
}
(三)GL 空间变换相关推荐
- Eigen库:(三)空间变换
我们将介绍几何模块提供的处理2D和3D旋转以及投影或仿射变换的方法. 1. 变换类型 // 下面的类型将d换成f就可以得到单精度的数据结构 Eigen::Matrix3d; //旋转矩阵3*3 Eig ...
- 空间变换网络--spatial transform network
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u011961856/article/details/77920970 CNN分类时,通常需要考虑输入 ...
- 形象理解线性代数(三)——列空间、零空间(核)、值域、特征值(特征向量)、矩阵与空间变换、矩阵的秩
这里,我们还是要以 形象理解线性代数(一)--什么是线性变换?为基础.矩阵对向量的作用,可以理解为线性变换,同时也可以理解为空间的变换,即(m*n)的矩阵会把一个向量从m维空间变换到n维空间. 一.矩 ...
- Paper:《Spatial Transformer Networks空间变换网络》的翻译与解读
Paper:<Spatial Transformer Networks空间变换网络>的翻译与解读 导读:该论文提出了空间变换网络的概念.主要贡献是提出了空间变换单元(Spatial Tra ...
- pytorch空间变换网络
pytorch空间变换网络 本文将学习如何使用称为空间变换器网络的视觉注意机制来扩充网络.可以在DeepMind paper 有关空间变换器网络的内容. 空间变换器网络是对任何空间变换的差异化关注的概 ...
- 坐标变换,空间变换的本质
坐标变换或空间变换,本质是相对坐标的变化,绝对坐标没变. 世界空间有两个物体A,B.将A变换到B的坐标空间意思是:将A从世界空间变换到B的局部坐标空间,也就是在B的局部坐标系中重新表示A的坐标(也就是 ...
- Opencv——几何空间变换(仿射变换和投影变换)
几何空间变换 [1]几何变换(空间变换)简述 [2]变换矩阵知识简述 齐次坐标的概念 几何运算矩阵 [3]图像的仿射变换 1.平移变换 2.比例缩放 3.旋转 4.对称变换(不做展示) 1.关于X轴变 ...
- 视觉SLAM笔记(13) 空间变换
视觉SLAM笔记(13) 空间变换 1. 3D空间变换 2. 相似变换 3. 仿射变换 4. 射影变换 1. 3D空间变换 3D 空间中的变换,除了欧氏变换之外,还存在其余几种,其中 欧氏变换 是最简 ...
- OpenCV之灰度空间变换
OpenCV入门之灰度空间变换 本系列博客主要以数字图像处理第三版为算法基础,以OpenCV为工具进行图像处理基础知识的分享.该教材的前两张基础知识这里不详述,有需要的读者自行查阅.本篇博客介绍第三章 ...
最新文章
- 2022华为首个「天才少年」,是从绩点1.8逆袭的复旦博士
- 简述原型模型的特点_软件工程简答题答案 第五版
- svn错误:Two top-level reports with no target
- python调用libvirt_通过python获取kvm虚拟机的监控信息(基于libvirt API)
- 和付费网盘说再见,自己起个网盘不香吗?| Java 开源项目
- Vue.js 代码优化浅谈
- atitit.提升备份文件复制速度(3) ----建立同步删除脚本
- android studio在夜神上打开_Android Studio 找不到夜神模拟器的解决办法
- hexo+yilia添加百度统计和Google统计
- HTTP状态码:400\500 错误代码(个人总结)
- MySQL 删除数据库
- X~N(0,1),如何求E(X^2),E(X^4),E(X^n)
- 机器人参加高考还拿高分,究竟怎么做到的?
- Schnorr signature Schnorr multi-signature
- 杜克计算机工程本科专业申请,杜克大学电气与计算机工程专业申请要求有哪些?...
- 数据结构视频教程 -《(东南大学 王茜)数据结构 (64讲)》
- 安卓玩机搞机技巧综合资源-----“另类更新“偷渡”操作步骤 无需解锁bl 无需内侧用户【十三】
- S32K144之时钟
- 倾角传感器组成和应用
- 工信部正式宣布,苹果何去何从?
热门文章
- 【Excel系列9】-- 28个基础图表
- 要求用户输入一个电子邮件。验证电子邮件格式是否正确。 电子邮件格式:XX@XX.com 实现方式:该字符串中必须包含@字符串和.字符串。 @不能出现在第一个位置,并且@位置大于.;
- 各省历年排污费入库金额
- #微积分#莱布尼茨公式
- 华为oj-名字的漂亮度
- MATLAB 最小生成树
- Batch Normalization函数详解及反向传播中的梯度求导
- 腾讯会议面试-音视频同步问题剖析
- matlab中normcdf函数用法,Matlab中标准正态分布的密度函数是normcdf(x,0,1)
- 乞力马扎罗的雪 - 笔记