OpenGL边用边学------2 经典照相机模型

2024-02-21 06:10

本文主要是介绍OpenGL边用边学------2 经典照相机模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 实际照相步骤
    • 1 布置场景和调整照相机位置
    • 3 选择镜头对焦Focus
    • 4 按下快门
    • 5 在电脑窗体中赞赏图片
  • OpenGL的相机模型
    • 0 确定胶片位置
    • 1 确立场景世界坐标系
    • 2 在世界坐标系中确定相机位置与方向
    • 3 在世界坐标系中建立物理世界模型
    • 4 视图变换与模型变换的抉择
    • 5 在照相机坐标系中确定可视范围对焦投影变换
    • 6 调用glBegin glEnd拍照
  • OpenGL相机模型与实际相机的不同
    • 1 物体和相机都能够随意移动
    • 2 终于的照片能够是多次拍摄合成的
    • 3 特殊的投影方式正投影
  • 相机模型使用建议
    • 1 尽量让编程符合这个模型
    • 2 注意区分两大坐标系世界坐标系和相机坐标系
    • 3 实例

学习OpenGL必须要有一个感性的认识,最经典的类比就是照相机照相模型。如今差点儿人人都有一部自带照相功能的手机了,所以这个模型对于绝大多数人来说都是非常easy理解的。

1 实际照相步骤

1.1 布置场景和调整照相机位置

照相模型
之所以把布置场景和调整相机位置放到了一起,是因为这两个步骤的顺序不是固定的,摄影师既能够自己移动相机。也能够指挥被拍的人移动位置。

1.3 选择镜头,对焦(Focus)

镜头的选择主要是为了达到合适的视角范围。镜头确定以后,焦距就确定了。

一般来说,调焦(Focus)并非改变镜头的焦距。而是改变镜头与胶片的距离(像距)。

凸透镜能成像,一般用凸透镜做照相机的镜头时,它成的最清晰的像一般不会正好落在焦点上,或者说,最清晰的像到光心的距离(像距)一般不等于焦距,而是略大于焦距。详细的距离与被照的物体与镜头的距离(物距)有关,物距越大,像距越小。(但实际上总是大于焦距)。

这里写图片描写叙述

1.4 按下快门

一切都调整好了,就能够拍照了。

按下快门的那一刻,相机位置、场景布置都定格了,不再改变。

感光器件(胶片)会记录下这一时刻的场景。绘制成一个矩形的二位像素图。

1.5 在电脑窗体中赞赏图片

然后就能够把照片转移到电脑中。使用看图软件把图片放到合适的位置进行赞赏了。

2 OpenGL的相机模型

2.0 确定胶片位置

OpenGL中没有真正的胶片,必须把拍摄到的图像放到一个指定的地方显示。这个地方就是视口。在上篇博文中已经专门介绍了视口的设置方法了。这里不再累述。

2.1 确立场景(世界)坐标系

与实际照相不同的是。OpenGL默认的物理世界里是没有不论什么物体的。须要程序猿通过代码来建立场景中的物体。

建模的最基本要素是确定物体的位置。而要描写叙述物体位置首先要做的就是确定一个世界(场景)坐标系

这个坐标系必须是标准的笛卡尔右手坐标系。而其原点和长度单位却没有不论什么限制,由程序猿依据实际须要自由确定。比如,对于整个城市的场景,原点能够设置在市政府。x,y方向能够分别设置为东西方向和南北方向,长度单位设置为米。而对于分子结构的场景,长度单位则可能是纳米了。

同其它状态变量一样,OpenGL的世界坐标系也有默认值。那就是一个标准右手三维直角坐标系。y轴向上,原点位置和长度单位未定义。

创建坐标系是程序猿的思维中进行的,无法直接体现到代码上,通过后面相机、物体的定位坐标数值来体现。

2.2 在世界坐标系中确定相机位置与方向

与场景中的其它物体一样,相机也是在世界坐标系中进行定位的。在OpenGL中,改变相机位置和方向的行为叫做视图变换,完毕这个功能的函数是gluLookAt()

void WINAPI gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz
);

首先,确定的是照相机的坐标,通过(eyex, eyey, eyez)确定。

其次,是确定镜头的朝向,通过瞄准线上一点(centerx,centery,centerz)指定,须要注意的是,这个点并非拍摄时对焦的点,仅仅是用来确定镜头的方向而已。终于方向就是从点(eyex,eyey,eyez)到(centerx,centery,centerz)的连线方向。

最后,是旋转镜头。通过指定向上方向上经过的一点(upx,upy,upz)确定。须要注意的是,向上方向是由(0。0。0)到(upx,upy,upz)连线确定的,与相机坐标(eyex,eyey,eyez)没有关系。

OpenGL同样会在初始化时。为相机的位置和方向在世界坐标系中指定一个默认值。那就是。照相机位于原点,镜头朝向z轴负方向。向上方向为y轴正方向。相当于调用了gluLookAt(0,0,0,0,0,0,0,1,0)

2.3 在世界坐标系中建立物理世界模型

与实际照相不同。OpenGL里的物体都是虚拟的,想象出来的。

详细来说。是通过在世界坐标系里确定其位置来描写叙述的。

这样的虚拟的特性给了OpenGL比实际照相很多其它的控制性。比如,虚拟的物体能够随意摆放,随意建立或删除。随意着色。随意形状。

仅仅要你敢想象。没有人能阻挡你建立一座倒立的房子。因为这些物体能够随意移动,所以全然能够把照相机始终固定,仅仅是通过移动物体来达到和移动相机同样的效果。相机成像的结果就是相机和物体相对位置来确定的,所以理论上移动物体和移动相机都能达到同样的效果。

实际上。OpenGL就是使用了一个矩阵来描写叙述这样的相对关系。这就是大名鼎鼎的模型视图矩阵

移动物体在OpenGL里被叫做模型变换。视图变换和模型变换改变的都是同一个模型视图矩阵。模型变换就是改动模型视图矩阵,OpenGL为最经常使用的三种变换提供了函数:

/*平移*/
void WINAPI glTranslatef(GLfloat x,GLfloat y,GLfloat z
);
/*旋转*/
void WINAPI glRotatef(GLfloat angle,GLfloat x,GLfloat y,GLfloat z
);
/*缩放*/
void WINAPI glScalef(GLfloat x,GLfloat y,GLfloat z
);

普通情况下,这三种变换全然能够满足程序的须要。假设须要特殊的变化,OpenGL也提供了直接操作矩阵的方式。


void WINAPI glMultMatrixf(const GLfloat *m
);

2.4 视图变换与模型变换的抉择

详细是採用视图变换还是模型变换。取决于详细的场景渲染需求,往往一种变换比还有一种变换更直接、更easy理解、更简单。

比如驾驶飞机游戏中,从飞机内部向外看时。则视图变换明显要更简单、更符合正常思维。

2.5 在照相机坐标系中确定可视范围。对焦(投影变换)

镜头有个横向有个视角问题。纵深也有范围,不可能看到无限远的物体。实际照相时镜头的不同决定了水平视角大小,光线的强弱决定了能拍摄的最大纵深。对焦决定了胶片位置。在OpenGL中,则通过一个函数完毕了这些功能。

OpenGL提供了例如以下函数来完毕这个任务。

void WINAPI glFrustum(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble zNear,GLdouble zFar
);

这里写图片描写叙述

这个可视范围也是在照相机坐标系中指定的。

照相机坐标系的定义例如以下:

  • 原点位于照相机本身
  • 照相机的向上方向(由gluLookAt指定)为y轴正方向,照相机朝向为z轴负方向。x轴依据右手定则确定;
  • 长度单位与世界坐标系同样

这样近平面左下角坐标就是(left, bottom, -near),右上角坐标是(right, top, -near)。
注意:參数中的zNear, zFar都是距离值。必须为正;其它參数则是坐标值。可正可负。

因为近平面也是终于的投影平面,所以zNear也就成了对焦距离了。

实际使用时,glFrustum中各个參数的确定不是非常方便。所以OpenGL提供了另外一个更方便调用的函数来确定可视范围。

gluPerspective()

void WINAPI gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar
);

当然,这个函数中的參数也是在相机坐标系中确定的。当中zNear, zFar的含义与glFrustum()中的同样。
fovy是在垂直方向的可视角度,单位为度。范围为(0.0,180.0),aspect是水平方向可视角度范围与垂直方向可视角度范围的比例,也就是水平方向可视范围为 fovy*aspect。

这个函数定义了一个对称的可视空间,用起来要比glFrustum方便非常多。

2.6 调用glBegin(); …; glEnd()拍照

前面的全部的设置确定了终于拍摄的范围、方向、存放地。最后一步就是进行实际拍摄了。在OpenGL中。拍摄动作是伴随建模一起的。

3 OpenGL相机模型与实际相机的不同

尽管用相机拍照过程来比喻OpenGL渲染过程非常适合。可是毕竟OpenGL是计算机软件行为,所以和真正的还是相机拍摄过程还是有非常多的不同之处。

3.1 物体和相机都能够随意移动

这个在前面已经说过了。

3.2 终于的“照片”能够是多次拍摄合成的

OpenGL的每一次glBegin(); …; glEnd(); 相当于一次拍摄。而终于的“照片”是多次拍摄的合成结果。并且每次拍摄都能够使用不同的场景、不同的相机位置、不同的视口….。

程序中能够无限次调用glBegin(); …; glEnd()进行拍摄。

3.3 特殊的投影方式—正投影

前面介绍的glFrustum()以非常接近实际相机的方式设置了可是范围与投影方式(透视投影)。

然而OpenGL毕竟是软件。灵活性要比实际相机强得多,它还提供了一种正投影的方式。这相当于照相机的镜头不是凸透镜,而是平面玻璃。现实中不可能存在这样的照相机。

void WINAPI glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble zNear,GLdouble zFar
);

这个函数确定的可视范围是一个平行于视线的长方体。同样也是在照相机坐标系中点定义坐标。

这里写图片描写叙述
可视范围内的物体,不管近远,投影到近平面上后都不改变其大小。

4 相机模型使用建议

4.1 尽量让编程符合这个模型

照相机模型非常好的反映了OpenGL内部的运算过程,非常适合构造场景时使用它来帮助思考。程序中也尽量使用这样的模型去实现。除非特殊须要,避免不符合该模型的操作方法,比如一帧图像多次渲染使用不同相机位置。可是使用同一个视口,这相当于拍摄了多张照片,然后叠加到了一起,easy让人摸不着头脑。

4.2 注意区分两大坐标系:世界坐标系和相机坐标系。

首先在世界坐标系中确定相机位置、视线方向、向上方向,然后在相机坐标系中确定可视范围。

世界坐标系的轴方向由程序猿随意定义,仅仅要满足笛卡尔右手定则就能够:比如数学上常见的三维坐标系。往往是z轴向上,而不是OpenGL中常见的y轴向上。

相机坐标系的原点,各轴方向则必须由相机,视线方向和向上方向来确定:原点必然位于相机本身,视线方向必然是z轴负方向。向上方向必然是y轴正向。

4.3 实例

以下是一个漫游观察四面体的小实例。

这里写图片描写叙述

初始化时,设置可视空间和相机初始位置。

// 安排相机glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(3, 0, 1,0, 0, 1,0, 0, 1);// 确定可视范围glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(100, 1, 0.5, 100);::InvalidateRect(hWnd, NULL, TRUE);

鼠标单击一下客户区,照相机就会绕z轴你是神旋转5度,可视空间不再改变。代码例如以下:

void OnLeftButtonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{static float a = 0;float x, y, z;x = 3 * cos(a*3.14/180);y = 3 * sin(a*3.14/180);z = 1;a += 5;while(a > 360) {a -= 360;}glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(x, y, z, 0, 0, 1, 0, 0, 1);::InvalidateRect(hWnd, NULL, TRUE);
}

实际的渲染代码为:

void OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{glClear(GL_COLOR_BUFFER_BIT);// 绘制世界坐标系glColor3f(1, 1, 1);glBegin(GL_LINES);glVertex3d(0, 0, 0);glVertex3d(100, 0, 0);glVertex3d(0, 0, 0);glVertex3d(0, 100, 0);glVertex3d(0, 0, 0);glVertex3d(0, 0, 100);glEnd();// 在原点处。建立一个四面体,四个顶点分别位于三个轴上。和原点处。

glEnable(GL_CULL_FACE); glCullFace(GL_BACK); glBegin(GL_TRIANGLES); glColor3f(1, 0, 0); glVertex3d(0, 1, 0); glVertex3d(1, 0, 0); glVertex3d(0, 0, 0); glColor3f(0, 1, 0); glVertex3d(1, 0, 0); glVertex3d(0, 0, 2); glVertex3d(0, 0, 0); glColor3f(0, 0, 1); glVertex3d(0, 0, 2); glVertex3d(0, 1, 0); glVertex3d(0, 0, 0); glColor3f(1, 1, 0); glVertex3d(1, 0, 0); glVertex3d(0, 1, 0); glVertex3d(0, 0, 2); glEnd(); HDC hdc = ::GetDC(hWnd); ::SwapBuffers(hdc); ::ReleaseDC(hWnd, hdc); }

执行截图:

这里写图片描写叙述

源代码下载

这篇关于OpenGL边用边学------2 经典照相机模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/730794

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

图神经网络模型介绍(1)

我们将图神经网络分为基于谱域的模型和基于空域的模型,并按照发展顺序详解每个类别中的重要模型。 1.1基于谱域的图神经网络         谱域上的图卷积在图学习迈向深度学习的发展历程中起到了关键的作用。本节主要介绍三个具有代表性的谱域图神经网络:谱图卷积网络、切比雪夫网络和图卷积网络。 (1)谱图卷积网络 卷积定理:函数卷积的傅里叶变换是函数傅里叶变换的乘积,即F{f*g}

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

AI Toolkit + H100 GPU,一小时内微调最新热门文生图模型 FLUX

上个月,FLUX 席卷了互联网,这并非没有原因。他们声称优于 DALLE 3、Ideogram 和 Stable Diffusion 3 等模型,而这一点已被证明是有依据的。随着越来越多的流行图像生成工具(如 Stable Diffusion Web UI Forge 和 ComyUI)开始支持这些模型,FLUX 在 Stable Diffusion 领域的扩展将会持续下去。 自 FLU

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号