opengl 学习(六)-----坐标系统与摄像机
坐标系统与摄像机
- 分类
- 引言
- 坐标系统
- 摄像机
- 教程
- 在CMake中使用全局定义预编译宏,来控制是否开启错误检查
- 补充
分类
opengl c++
引言
OpenGL希望在每次顶点着色器运行后,我们可见的所有顶点都为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说,每个顶点的x,y,z坐标都应该在-1.0到1.0之间,超出这个坐标范围的顶点都将不可见。
我们通常会自己设定一个坐标的范围,之后再在顶点着色器中将这些坐标变换为标准化设备坐标。然后将这些标准化设备坐标传入光栅器(Rasterizer),将它们变换为屏幕上的二维坐标或像素。
将坐标变换为标准化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的
在这个工程中,物体的顶点在最终转化为屏幕坐标之前还会被变换到多个坐标系统(Coordinate System):
将物体的坐标变换到几个过渡坐标系(这样的优点在于,在这些特定的坐标系统中,一些操作或运算更加方便和容易)
对我们来说比较重要的总共有5个不同的坐标系统:
局部空间(Local Space,或者称为物体空间(Object Space))
世界空间(World Space)
观察空间(View Space,或者称为视觉空间(Eye Space))
裁剪空间(Clip Space)
屏幕空间(Screen Space)
这就是一个顶点在最终被转化为片段之前需要经历的所有不同状态。
为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。我们的顶点坐标起始于局部空间(Local Space),在这里它称为局部坐标(Local Coordinate),它在之后会变为世界坐标(World Coordinate),观察坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。下面的这张图展示了整个流程以及各个变换过程做了什么:

局部坐标是对象相对于局部原点的坐标,也是物体起始的坐标。
下一步是将局部坐标变换为世界空间坐标,世界空间坐标是处于一个更大的空间范围的。这些坐标相对于世界的全局原点,它们会和其它物体一起相对于世界的原点进行摆放。
接下来我们将世界坐标变换为观察空间坐标,使得每个坐标都是从摄像机或者说观察者的角度进行观察的。
坐标到达观察空间之后,我们需要将其投影到裁剪坐标。裁剪坐标会被处理至==-1.0到1.0的范围内,并判断哪些顶点将会出现在屏幕上==。
最后,我们将裁剪坐标变换为屏幕坐标,我们将使用一个叫做视口变换(Viewport Transform)的过程。视口变换 将位于-1.0到1.0范围的坐标 变换到 由glViewport函数所定义的坐标范围内。最后变换出来的坐标将会送到光栅器,将其转化为片段。
哦,所以说,glViewport函数的作用就是将裁剪后的坐标变换为屏幕坐标,下次你再遇到的时候就应该了解这个函数了。
其实耐心去看的话,是能看懂的,但是工作中总是很心急,想快点做出效果,结果就是遗漏了重要的知识点,现在第二遍我才看到这个。
我们之所以将顶点变换到各个不同的空间的原因是有些操作在特定的坐标系统中才有意义且更方便。
好好理解下面这个例子:
例如,
当需要对物体自身进行修改的时候(比如星球自转),在局部空间中来操作会更说得通;
如果要对一个物体做出一个相对于其它物体位置的操作时(比如绕着一个东西进行旋转),在世界坐标系中来做这个才更说得通,等等。
接下来我们将要更仔细地讨论各个坐标系统。
坐标系统
坐标标准化处理



x = (event.pos().x - this->width/2) / this->width/2;
y = - (event.pos().y - this->height/2) / this->height/2;
摄像机
明确一点:
OpenGL本身没有摄像机(Camera)的概念,
但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动。
不要忘记正z轴是从屏幕指向你的,如果我们希望摄像机向后移动,我们就沿着z轴的正方向移动。
教程
https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/
在CMake中使用全局定义预编译宏,来控制是否开启错误检查
这个好厉害:opengl的错误检查
https://www.bilibili.com/video/BV1EZ4y1n72m/?p=21&spm_id_from=pageDriver

补充

__FILE__和__LINE__
它们会在编译的时候被替换成编译时对应的文件与行号。





#include <assert.h>
void checkErroe()
{GLenum errorCode = glGetError();std::string error = "";if(errorCode != GL_NO_ERROR){switch(errorCode){case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;case GL_INVALID_VALUE: error = "GL_INVALID_VALUE"; break;case GL_INVALID_OPEATION: error = "GL_INVALID_OPEATION"; break;case GL_OUT_OF_MEMORY: error = "GL_OUT_OF_MEMORY"; break;default:error = "UNKOWN";break;}std::cout<<error<<std::endl;asssert(false);//断言,一但出现错误,就让程序暂停}
}




感觉还是看视频效率高些,看书看不进去,红红火火哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
相关文章:
opengl 学习(六)-----坐标系统与摄像机
坐标系统与摄像机 分类引言坐标系统摄像机教程在CMake中使用全局定义预编译宏,来控制是否开启错误检查补充 分类 opengl c 引言 OpenGL希望在每次顶点着色器运行后,我们可见的所有顶点都为标准化设备坐标(Normalized Device Coordinate, NDC)。也就是说ÿ…...
分库分表场景下多维查询解决方案(用户+商户)
在采用分库分表设计时,通过一个PartitionKey根据散列策略将数据分散到不同的库表中,从而有效降低海量数据下C端访问数据库的压力。这种方式可以缓解单一数据库的压力,提升了吞吐量,但同时也带来了新的问题。对于B端商户而言&#…...
vue学习日记14:工程化开发脚手架Vue CLI
一、概念 二、安装 1.全局安装&查看版本 注意启动cmd输入命令 要以管理员运行哦 安装了一次就行以后不用再创建了 yarn global addvue/cli vue --version 显示了版本号即可 2.创建项目架子 创建项目的路径在哪 项目就在哪 项目名字不能用中文 vue create project-n…...
java Flink(四十三)Flink Interval Join源码解析以及简单实例
背景 之前我们在一片文章里简单介绍过Flink的多流合并算子 java Flink(三十六)Flink多流合并算子UNION、CONNECT、CoGroup、Join 今天我们通过Flink 1.14的源码对Flink的Interval Join进行深入的理解。 Interval Join不是两个窗口做关联,…...
JsonUtility.ToJson 和UnityWebRequest 踩过的坑记录
项目场景: 需求:我在做网络接口链接,使用的unity自带的 UnityWebRequest ,数据传输使用的json,json和自定义数据转化使用的也是unity自带的JsonUtility。使用过程中发现两个bug。 1.安全验证失败。 报错为:…...
面试算法-69-三角形最小路径和
题目 给定一个三角形 triangle ,找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 1 的两个结点。也就是说,如果正位于当前行的下标 i ,那…...
流畅的 Python 第二版(GPT 重译)(九)
第四部分:控制流 第十七章:迭代器、生成器和经典协程 当我在我的程序中看到模式时,我认为这是一个麻烦的迹象。程序的形状应该只反映它需要解决的问题。代码中的任何其他规律性对我来说都是一个迹象,至少对我来说,这表…...
单片机学到什么程度才可以去工作?
单片机学到什么程度才可以去工作? 如果没有名校或学位的加持,你还得再努力一把,才能从激烈的竞争中胜出。以下这些技能可以给你加分,你看情况学,不同行业对这些组件会有取舍: . Cortex-M内核:理解MCU内核各部件的工作机制&#…...
内网穿透方案
内网穿透 有几种流行的内网穿透软件可供选择,它们都能帮助你在内网环境中建立与外部网络的连接。以下是其中一些常用的内网穿透软件: Ngrok:Ngrok 是一个简单易用的内网穿透工具,可以快速创建安全的公共 URL,让你可以…...
WordPress菜单函数wp_nav_menu各参数
wordpress主题制作时,常常会在不同的位置调用不同的菜单,使用下面的这个代码,再加上CSS给菜单做新的样式,可满足wordpress模板制作时对菜单调用的所有需求。 wp_nav_menu( array( theme_location > ,//导航别名 menu > , /…...
类于对象(上)--- 类的定义、访问限定符、计算类和对象的大小、this指针
在本篇中将会介绍一个很重要和很基础的Cpp知识——类和对象。对于类和对象的篇目将会有三篇,本篇是基础篇,将会介绍类的定义、类的访问限定符符和封装、计算类和对象的大小、以及类的 this 指针。目录如下: 目录 1. 关于类 1.1 类的定义 2 类…...
提升交付效率:Booking.com 金融技术团队的成功实践
Booking.com 金融技术业务部门的团队对其平台的后端和前端实施了一系列改进措施,并通过 DORA 指标将交付性能提高了一倍。此外,还使用了微前端 (MFE) 模式,将单体 FE 应用程序分解为多个可单独部署的分解应用程序。 2022 年年中,B…...
【消息队列开发】 实现ConsumerManager类——消费消息的核心逻辑
文章目录 🍃前言🌴扫描线程的实现🌲实现消费消息🌳实现addConsumer()方法🎋VirtualHost类订阅消息的完善⭕总结 🍃前言 本次开发目标 实现消费消息的核心逻辑 🌴扫描线程的实现 我们先给Cons…...
【Three.js】使用精灵图Sprite创建面朝相机的文本标注
目录 🐝前言 🐝canvas创建文字 🐝将canvas作为纹理贴图加载到sprite中 🐝封装方法 🐝前言 在Three.js中精灵Sprite是一个总是面朝摄像机的平面,它通常和纹理贴图结合使用,贴图可以是一张图…...
C++中的类模板
C中的类模板 类模板 类模板在C中是一种非常强大的工具,它允许程序员编写与数据类型无关的代码。简单来说,类模板允许你定义一个蓝图,这个蓝图可以用来生成具体类型的类。使用类模板可以提高代码的复用性,减少重复代码࿰…...
【每日一题】好子数组的最大分数
Tag 【单调栈】【暴力枚举】【数组】【2024-03-19】 题目来源 1793. 好子数组的最大分数 解题思路 本题和 84. 柱状图中最大的矩形 一样,计算的都是最大矩形的面积。只不过多了一个约束:矩形必须包含下标 k。 以下的方法一和方法二是 84. 柱状图中最…...
Vue2(七):超详细vue开发环境搭建(win7),nodejs下载与安装,安装淘宝镜像(报错已解决),配置脚手架
一、安装node.js 本来想粗略写一下的,但是搭建脚手架的时候,遇到了很多问题,浪费快两天时间,记录一下自己的解决办法希望对你们有帮助! 1.下载nodejs 安装包下载链接【CNPM Binaries Mirror】 下载我划线的这个&am…...
【Web】记录CISCN 2021 总决赛 ezj4va题目复现——AspectJWeaver
目录 前言 原理分析 step 0 step 1 EXP 前文:【Web】浅聊Java反序列化之AspectJWeaver——任意文件写入-CSDN博客 前言 这就是当年传说中的零解题嘛😭,快做🤮了 有了之前的经验,思路顺挺快的,中间不…...
视频技术1:使用ABLMediaServer推流rtsp
ABLMediaServer定位是高性能、高稳定、开箱即用、商用级别的流媒体服务器 下边展示了如何把1个mp3作为输入源,转换为rtsp流的过程。 作用:用rtsp模拟摄像头的视频流 1、启动ABLMediaServer ABLMediaServer-2024-03-13\WinX64\ABLMediaServer.exe 配…...
HTML5+CSS3+JS小实例:创意罗盘时钟
实例:创意罗盘时钟 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
