1.openGL概述(笔记)

操作流程

一个用来渲染图像的OpenGL程序需要执行操作如下:

  • 从OpenGL的几何图元中设置数据,用于构建形状
  • 使用不同的着色器(shader)对输入的图元数据执行计算操作,判断它们的位置、颜色,以及其他渲染属性。
  • 将输入图元的数学描述转换为与屏幕位置对应的像素片元(fragment)。这一步也称作光栅化(rasterization)。(OpenGL中的片元若最终渲染为图像,那它就是像素。)
  • 最后,针对光栅化过程产生的每个片元,执行片元着色器(fragment shader),从而决定这个片元的最终颜色和位置。
  • 如果有必要,还需要对每个片元执行一些额外的操作,例如判断片元对应的对象是否可见,或者将片元对应的对象是否可见,或者将片元的颜色与当前屏幕位置的颜色进行融合。

所有OpenGL程序的基本结构通常都是:

  • 初始化物体渲染所对应的状态。
  • 设置需要渲染的物体。

BS架构

OpenGL是使用客户端—服务端的形式实现的,我们编写的应用程序可以看做客户端,而计算机图形硬件厂商所提供的OpenGL实现可以看做服务端。OpenGL的某些实现(例如X窗口系统的实现)允许服务端和客户端在一个网络内的不同计算机上运行。

X窗口

X窗口(X Window System,也常简称为X或X11)是一种用于UNIX及类UNIX系统的标准图形化用户界面(GUI)系统。

X窗口系统基于服务器-客户端的网络架构。服务端(X Server)负责管理来自客户端(X Client)的连接,处理输入设备(如键盘和鼠标)的输入,并向客户端返回像素数据以更新界面。这种架构使得X窗口系统能够支持远程绘制界面,即服务端和客户端可以运行在不同的机器上,并通过网络协议进行通信。

光栅化系统

渲染(render),表示计算机从模型创建最终图像的过程。OpenGL是基于光栅化的系统,但是也有别的方法用于生成图像。例如光线追踪(ray tracing),不过,就算用到了光线追踪技术的系统,同样有可能需要用到OpenGL来显示图像,或者计算图像生成所需的信息。

对于,OpenGL的最新版本,诸如光线追踪、光子映射(photon mapping)、路径跟踪(path tracing)以及基于图像的渲染(image-based rendering)这样的技术都可以相对简单地在可编程图形硬件端实现。

着色器

OpenGL另一个最本质的概念叫做着色器,它是图形硬件设备所执行的一类特殊函数。

理解着色器的最好的方法是把它看做,专为图形处理单元(通常也叫做GPU)编译的一种小型程序。

在OpenGL中,会用到六种不同的着色阶段(shader stage):

  • 顶点着色器阶段(vertex shading stage)
  • 细分着色阶段(tessellation shading stage)
    • 细分控制着色器(tessllation control shader)
    • 细分赋值着色器(tessellation evaluation shader)
  • 几何着色阶段(geometry shading stage)
  • 片元着色阶段(fragment shading stage)
  • 计算着色阶段(compute shading stage)

最常用的是顶点着色器(vertex shader)和片元着色器(fragment shader),前者用于处理顶点数据,后者用于处理光栅化后的片元数据。

最终生成的图像包含了屏幕上绘制的所有像素点。像素(pixel)是显示器上最小的可见单元。计算机系统将所有的像素保存到帧缓存(framebuffer)当中,帧缓存是由图形硬件设备管理的一块独立内存区域,可以直接映射到最终的显示设备上。

帧缓存

帧缓存,也称为帧缓冲存储器,是计算机图形学中的一个重要概念,主要用于存储和管理输出到显示器的像素数据。以下是关于帧缓存的详细解释:

一、定义

帧缓存是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。在Linux系统中,帧缓存被抽象为显示设备的一个接口,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。

二、功能
  1. 存储像素数据:帧缓存是一个内存区域,用于保存在计算机图形渲染中生成的图像。它存储了每个像素的颜色、深度和其他相关信息。
  2. 实现图形显示:通过提供一块内存区域来存储和管理输出到显示器的像素数据,帧缓存实现了图形显示的各类功能。渲染过程中,计算机会将三维数据转化为二维像素信息,并将这些像素信息存储到帧缓存中,最终通过显示设备实时显示在屏幕上。
  3. 支持多种渲染技术:帧缓存可以支持多种渲染技术,如阴影、反射、折射等效果的模拟,以及光照计算、纹理映射等高级图形处理技术。
三、特点
  1. 实时性:帧缓存中的数据是实时的,如果不捕获,每一帧都会被丢弃。这使得帧缓存能够支持实时图形渲染和动态图像显示。
  2. 灵活性:帧缓存允许应用程序直接控制屏幕显示内容,提供了高度的灵活性。开发者可以根据需要自由修改帧缓冲区中的数据,以实现各种自定义的显示效果。
  3. 跨平台性:帧缓存作为一种低级的通用设备,能够跨平台工作,支持多种硬件平台,如x86、PPC、m68k和SPARC等,甚至在嵌入式设备上也能正常工作。
四、应用
  1. 游戏开发:在游戏开发中,帧缓存用于存储和管理游戏画面的像素数据,实现高质量的图形渲染和动态效果。
  2. 多媒体应用:在视频编辑、图像处理等多媒体应用中,帧缓存用于实时显示和处理视频帧和图像帧。
  3. 嵌入式系统:在嵌入式系统中,帧缓存也扮演着重要角色,用于实现图形用户界面(GUI)和图形显示功能。
五、总结

帧缓存是计算机图形学中的一个核心概念,它通过提供一块内存区域来存储和管理输出到显示器的像素数据,实现了图形显示的各类功能。帧缓存具有实时性、灵活性和跨平台性等特点,广泛应用于游戏开发、多媒体应用和嵌入式系统等领域。

渲染管线

渲染管线(rendering pipeline),它是一系列数据处理过程,并且将应用程序的数据转换到最终渲染的图像。

在这里插入图片描述

只有顶点着色器和片元着色器是必须的,细分和几何着色器是可选的步骤。

  1. 准备向OpenGL传输数据:OpenGL需要将所有的数据都保存到缓存对象(buffer object)中,它相当于由OpenGL维护的一块内存区域。

  2. 将数据传输到OpenGL:缓存初始化完毕后,调用绘制命令来请求渲染几何图元,而绘制通常就是将顶点数据传输到OpenGL服务端。可将一个顶点视为一个需要统一处理的数据包,数据包中是我们需要的任何数据,包括位置数据,以及其他决定颜色的数据。

  3. 顶点着色:对于绘制命令传输的每个顶点,都会调用顶点着色器处理。可仅做传递,也可进行位置变换、光照计算等等。

  4. 细分着色:细分着色器使用面元(patch)来描述一个物体的形状,并且使用相对简单的面片几何体连接,来完成细分的工作,其结果是几何图元的数量增加,并且模型的外观会变得更加平顺。

  5. 几何着色:此着色阶段,允许在光栅化之前对每个几何图元做更进一步的处理,例如创建新图元。

  6. 图元装配:此阶段是将顶点与相关的几何图元之间组织起来。

  7. 剪切:对视口之外的,顶点相关的图元作出改动,保证相关的像素不会在视口外绘制。它是由OpenGL自动完成。

  8. 光栅化:将更新后的图元传递到光栅化(rasterizer)单元,生成对应的片元。光栅化的工作是判断某一部分几何体(点、线或者三角形)所覆盖的屏幕空间。得到屏幕空间信息及输入的顶点数据后,光栅化单元对片元着色器中的每个可变变量进行线性插值,结果传递给用户的片元着色器。

    光栅化是一个片元的开始,片元着色器是用于计算一个片元的最终颜色,但它不是针对片元的所有操作。

OpenGL实现光栅化和数据插值的方法是与具体平台相关。

  1. 片元着色:通过编程控制屏幕上显示颜色的阶段叫片元着色阶段。这个阶段,来计算片元的颜色和深度值。

顶点着色(包括细分和几何着色)决定了一个图元应该位于屏幕的什么位置,片元着色使用这些信息,决定片元的颜色应该是什么。

  1. 逐片元的操作:片元操作的下一步,是最后的独立片元处理过程。这个过程使用深度测试(depth test,或者通常也称作z缓存)和模版测试(stencil test)的方式来决定一个片元是否可见。

    片元成功通过测试后,它会被绘制到帧缓存中,对应像素的颜色会被更新;若开启融混(blending)模式,片元颜色会与该像素颜色叠加,形成新颜色写进帧缓存。

API接口

初始化顶点数组对象

  • void glCreateVertexArrays(GLsizei n,GLuint *arrays);

    返回n个未使用的对象名到数组arrays中,用作顶点数组对象。

  • void glBindVertexArray(GLuint array);

    如果输入的变量array非0,并且是glCreateVertexArrays()所返回的,那么会激活这个顶点数组对象,并且直接影响对象中所保存的顶点数组状态。

    如果输入的变量为0,那么OpenGL将不再使用之前绑定的顶点数组。

  • void glDeleteVertexArrays(GLsizei n,const Gluint *arrays);

    删除n个在arrays中定义的顶点数组对象,这样所有的名称可以再次用作顶点数组。

    如果绑定的顶点数组已经被删除,那么当前绑定的顶点数组对象被重设为0,并且不再存在一个当前对象。

    在arrays当中未使用的名称都会被释放,但是当前顶点数组的状态不会发生任何变化。

  • GLboolean gllsVertexArray(GLuint array);

    如果array是一个已经用glCreateVertexArrays()创建且没有被删除的顶点数组对象的名称,那么返回GL_TRUE。

    如果array为0或者不是任何顶点数组对象的名称,那么返回GL_FALSE。

分配缓存对象

  • void glGenBuffers(GLsizei n,GLuint *buffer);

    返回n个当前未使用的缓存对象名称,并保存到buffers数组中。返回到buffers中的名称不一定是连续的整型数据。如果n是负数,那么产生GL_INVALID_VALUE错误。

    这里返回的名称表示创建的缓存对象,带有默认可用状态。

  • void glBindBuffer(GLenum target,GLuint buffer);

    指定当前激活的缓存对象。

    target必须设置为一下类型中的一个:GL_ARRAY_BUFFER、GL_ATOMIC_COUNTER_BUFFER、GL_ELEMENT_ARRAY_BUFFER、GL_PIXEL_PACK_BUFFER、GL_PIXEL_UNPACK_BUFFER、GL_COPY_READ_BUFFER、GL_COPY_WRITE_BUFFER、GL_SHADER_STORAGE_BUFFER、GL_QUERY_RESULT_BUFFER、GL_DRAW_INDIRECT_BUFFER、GL_TRANSFORM_FEEDBACK_BUFFER和GL_UNIFORM_BUFFER。

    buffer设置的是要绑定的缓存对象名称。

  • void glDeleteBuffers(GLsizei n,const GLuint *buffers);

    删除n个保存在buffers数组中的缓存对象。被释放的缓存对象可以重用(例如,使用glCreateBuffers)。

    如果删除的缓存对象已经被绑定,那么该对象的所有绑定将会重置为默认的缓存对象,即相当与用0作为参数执行glBindBuffer()的结果。如果试图删除不存在的缓存对象,或者缓存对象为0,那么将忽略该操作(不会产生错误)。

  • GLboolean gllsBuffer(GLuint buffer);

    如果buffer是一个已经分配并且没有释放的缓存对象的名称,则返回GL_TRUE。

    如果buffer为0或者不是缓存对象的名称,则返回GL_FALSE。

将数据载入缓存对象

  • void glNameBufferStorage(GLuint buffer,GLsizeiptr size,const void*data,GLbitfield flags);

    在OpenGL服务端内存中分配size个存储单元(通常为byte),用于存储数据或者索引。

    该函数作用于名为buffer的缓存区域。它不需要设置target参数。

    size表示存储数据的总数量。这个数值等于data中存储的元素的总数乘以单元元素存储空间的结果。

    data要么是一个客户端内存的指针,以便初始化缓存对象,要么是NULL。如果传入的指针合法,那么将会有size大小的数据从客户端拷贝到服务端。如果传入NULL,那么将保留size大小的未初始化的数据,以备后用。

    flags提供了缓存中存储的数据相关的用途数据。它是下面一系列标识量经过逻辑"与"运算的总和:GL_DYNAMIC_STORAGE_BIT、GL_MAP_READ_BIT、GL_MAP_WRITE_BIT、GL_MAP_PERSISTENT_BIT、GL_MAP_COHERENT_BIT和GL_CLIENT_STORAGE_BIT。

    如果所需的size大小超过了服务端能够分配的额度大小,那么glNamedBufferData()将产生一个GL_OUT_OF_MEMORY错误。如果flags包含的不是可用的模式值,那么将产生GL_INVALID_VALUE错误。

顶点着色器关联顶点属性数组

  • void glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid* pointer);

    设置index(着色器中的属性位置)位置对应的数据值。

    pointer 表示缓存对象中,从起始位置开始计算的数组数据的偏移值(假设起始地址为0),使用基本的系统单位(byte)。(BUFFER_OFFSET(0),这里设置为0,因为数据是从缓存对象的第一个字节(地址为0)开始的。)

    size 表示每个顶点需要更新的分量数目,可以是1、2、3、4或者GL_BGRA。

    type 指定了数组中每个元素的数据类型(GL_BYTE、GL_UNSIGNED_BYTE、GL_SHORT、GL_UNSIGNED_SHORT、GL_INT、GL_UNSIGNED_INT、GL_FIXED、GL_HALF_FLOAT、GL_FLOAT或GL_DOUBLE)。

    normalized 设置顶点数据在存储前是否需要进行归一化(或者使用glVertexAttribFourN*())。

    stride 是数组中每两个元素之间的大小偏移值(byte)。如果stride为0,那么数据应该紧密地封装在一起。

渲染图像

  • 首先清除帧缓存的数据,再进行渲染

    void glClearBufferfv(GLenum buffer,GLint drawbuffer,const GLfloat *value);
    

    清除当前绘制帧缓存中的指定缓存类型,清除结果为value。

    参数buffer:设置了要清除的缓存类型,它可以是GL_COLOR、GL_DEPTH,或者GL_STENCIL。

    参数drawbuffer:设置了要清除的缓存索引。如果当前绑定的是默认帧缓存,或者buffer设置为GL_DEPTH或GL_STENCIL,那么drawbuffer必须是0。否则它表示需要被清除的颜色缓存的索引。

    参数value:是一个数组的指针,其中包含了一个或者四个浮点数,用来设置清除缓存之后的颜色。如果buffer设置为GL_COLOR,那么value必须是一个最少四个数值的数组,以表示颜色值。如果buffer是GL_DEPTH或者GL_STENCIL,那么value可以是一个单独的浮点数,分别用来设置深度缓存或模版缓存清除后的结果。

  • 渲染绘制

    void glDrawArrays(GLenum mode,GLint first,GLsizei count);
    

    使用当前绑定的顶点数组元素来建立一系列的几何图元,起始位置为first,而结束位置为first+count-1。

    mode 设置了构建图元的类型,它可以是GL_POINTS、GL_LINES、GL_LINE_STRIP、GL_LINE_LOOP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN和GL_PATCHES中的任意一种。

启用和禁用OpenGL操作

  • 操作模式的开启和关闭

    void glEnable(GLenum capability);
    void glDisable(GLenum capability);
    

    glEnable()会开启一个模式,glDisable()会关闭它。

    例如:GL_DERTH_TEST可以用来开启或关闭深度测试;

    GL_BLEND可以用来控制融合的操作;

    GL_RASTERIZER_DISCARD用于transfrom feedback过程中的高级渲染控制。

  • 检查模式是否启动

    GLboolean glIsEnabled(GLenum capability);
    

    根据是否启用当前指定的模式,返回GL_TRUE或者GL_FALSE。

NEHE的OPENGL教程 第42课 多视窗口… NEHE的OPENGL教程 第42课 多视窗口… NeHe的OPENGL中文教程:第41课 体… NeHe的OPENGL中文教程:第40课 绳… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第39课 物… NeHe的OPENGL中文教程:第38课 从… NeHe的OPENGL中文教程:第37课 卡… 愚人节十大IT假新闻:Opera浏览器… NeHe的OPENGL中文教程:第36课 放… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第35课 AVI… NeHe的OPENGL中文教程:第34课 从… NeHe的OPENGL中文教程:第33课 加… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第32课 Alp… NeHe的OPENGL中文教程:第31课 模… NEHE的OPENGL中文教程:第30课 碰… NEHE的OPENGL中文教程:第30课 碰… NeHe的OPENGL中文教程:第29课 Bli… NeHe的OPENGL中文教程:第28课 贝… NeHe的OPENGL中文教程:第27课 影… NeHe的OPENGL中文教程:第26课剪裁… NeHe的OPENGL中文教程:第25课 变… NeHe的OPENGL中文教程:第24课 TAG… NeHe的OPENGL中文教程:第23课 球… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第22课 凸… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第21课 反… NeHe的OPENGL中文教程:第20课 蒙… NeHe的OPENGL中文教程:第19课 粒… NeHe的OPENGL中文教程:第18课 二… NeHe的OPENGL中文教程:第17课 2D… NeHe的OPENGL中文教程:第16课 雾 NeHe的OPENGL中文教程:第15课 图… NeHe的OPENGL中文教程:第14课 图… NeHe的OPENGL中文教程:第13课 位… NeHe的OPENGL中文教程:第12课 显… NeHe的OPENGL中文教程:第11课 飘… NeHe的OPENGL中文教程:第十课 漫… NeHe的OPENGL中文教程:第九课 漂… NeHe的OPENGL中文教程:第八课 Alp… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第七课 纹… NeHe的OPENGL中文教程:第六课 纹… NeHe的OPENGL中文教程:第五课 向3… NeHe的OPENGL中文教程:第四课 旋… NeHe的OPENGL中文教程:第三课 着… NeHe的OPENGL中文教程:第二课 多… NeHe的OPENGL中文教程:第一课 新… NeHe的OPENGL中文教程:第一课 新… DirectX与OpenGL方面的经典电子书… VC++ 6.0下OpengGL配置以及glut配… 怎样开始学习OpenGL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值