计算机图形学—从0开始构建一个OpenGL软光栅教程

kuaidelasi · · 293 次点击 · 开始浏览    置顶

一、OpenGL 的优点包括:(/s/1MQuP0NnM4dgMY8mWf6931Q 提取码: c37y) 跨平台性: OpenGL 可以在许多不同的平台上运行,包括 Windows、Linux、macOS 和 Android。 高性能: 由于 OpenGL 可以使用显卡硬件加速图形渲染,因此可以提供高性能的图形处理。 灵活性: OpenGL 提供了许多灵活的功能,可以满足各种不同的应用程序需求。 开放标准: OpenGL 是一个开放标准,可以与其他开放标准进行集成,例如 OpenCL 和 OpenAL。 尽管 OpenGL 有许多优点,但它也有一些缺点。例如,OpenGL 缺乏一些现代图形 API 的高级功能,例如自动化的着色器管理和分布式渲染。然而,OpenGL 仍然是一个广泛使用的图形库,用于创建高性能和跨平台的图形应用程序。 二、OpenGL 专业词解析 1.OpenGL上下文[context] (1),在应用程序调用任何OpenGL指令之前,需要首先创建一个OpenGL的上下 文,这个上下文是一个非常庞大的状态机,保存了OpenGL中的各种状态,也是OpenGL指令执行的基础; (2),由于OpanGL上下文是一个巨大的状态机,切换上下文往往会产生较大的开销,但是不同绘制模块可能需要使用完全独立的状态管理,因此,可以在应用程序中分别创建多个不同的上下文,在不同的线程中使用不同的上下文,上下文之间共享纹理,缓冲区等资源,这样的方案,会比反复切换上下文或者大量修改渲染状态更加合理高效 2.顶点数组和顶点缓冲区 画图一般是先画好骨架,然后再往骨架里面填充颜色,这对与OpenGL也是一样的,顶点数据就是要画的图像的骨架,和现实中不同的是:OpenGL中的图像都是由图元组成的,在OpenGL ES中,有3种类型的图元:点,线,三角形,在那些顶点数据最终存储在哪里呢?开发者可以选择设定的函数指针,再调用绘制方法的时候,直接由内存传入顶点数据,也就是说这部分数据之前是存储在内存当中,被称为顶点数组,而性能更高的做法是提前分配一块显存,将顶点数据预先传入当中,这部分显存,就被成为顶点缓冲区。顶点指的是我们在绘制一个图形时,它的顶点位置数据,而这个数据可以直接存储在数组中或者将其缓存到GPU内存中。 3.顶点着色器(VertexShader) 一般用来处理图形每个顶点变化【旋转、平移、投影等】; 顶点着色器是OpenGL中用于计算顶点属性的程序,顶点着色器是逐顶点运算的程序,也就是说每个顶点数据都会执行一次顶点着色器,当然这是并行的,并且顶点着色器运行中无法访问其他顶点的数据 一般来说典型的需要计算的顶点属性主要包括坐标变换,逐顶点光照运算等待,顶点坐标由自身坐标装换到归一化坐标系的运算,就是在这里发生的 三、OpenGL渲染状态机 渲染所需数据已经传输到显存中时,我们如何执行GPU的渲染命令呢? GPU的渲染指令是非常底层的,涉及显卡类型等硬件参数,这样复杂的指令让我们去调用是不可能的。但是我们有OpenGL。 渲染是一套固定的流程,我们无法对接GPU的底层指令,那我们是否可以建立一个通用的、无关硬件的渲染模型呢?当然可以,这就是OpenGL。 渲染是一个流程,这个过程中拥有很多可设置的选项,我们称这些选项为OpenGL的状态。所谓状态机,即拥有众多参数作为状态,当在不同的状态情况下会做出不同的反应,例如在不同的场景选项下呈现出不同的渲染结果。 OpenGL是一个完整的渲染状态机,Khronos组织制定并维护了OpenGL,换句话说:他们建立了OpenGL的状态机模型。这个模型是用于渲染的,它包含很多参数作为状态。针对这个模型,Khronos组织制定了OpenGL应该包含的函数,这些函数包括一些状态设置函数(State-changing Function)和状态应用函数(State-using Function)。使用状态设置函数可以改变OpenGL上下文即OpenGL的状态,使用状态应用函数会根据当前OpenGL的状态执行一些操作。 四、OpenGL工具库 OpenGL Utility Toolkit 包含大约30多个函数,函数名前缀为glut。   glut是不依赖于窗口平台的OpenGL工具包,目的是隐藏不同窗口平台API的复杂度。函数以glut开头,它们作为aux库功能更强的替代品,特别适合于开发不需要复杂界面的OpenGL示例程序。对于有经验的程序员来说,一般先用glut理顺3D图形代码,然后再集成为完整的应用程序。   这部分函数主要包括:   (1)窗口操作函数,窗口初始化、窗口大小、窗口位置等函数glutInit() glutInitDisplayMode() glutInitWindowSize() glutInitWindowPosition()等。   (2)回调函数。响应刷新消息、键盘消息、鼠标消息、定时器函数等,GlutDisplayFunc() glutPostRedisplay() glutReshapeFunc() glutTimerFunc() glutKeyboardFunc() glutMouseFunc()。   (3)创建复杂的三维物体。这些和aux库的函数功能相同。创建网状体和实心体。如glutSolidSphere()、glutWireSphere()等。在此不再叙述。   (4)菜单函数。创建添加菜单的函数GlutCreateMenu()、glutSetMenu()、glutAddMenuEntry()、glutAddSubMenu() 和glutAttachMenu()。   (5)程序运行函数,glutMainLoop()。 五、使Java层数据可以被OpenGL存取 在java层完成顶点的定义后,但是,在OpenGL可以存取它们之前,我们仍然需要完成另外一步。主要的问题是这些代码运行的环境与OpenGL运行的环境使用了不同的语言,我们需要理解如下两个主要的概念。 (1)当我们在模拟器或者设备上编译和运行Java代码的时候,它并不是直接运行在硬件上的;相反,它运行在一个特殊的环境上,即Dalvik虚拟机(Dalvik virtualmachine);运行在虚拟机上的代码不能直接访问本地环境(nativeenvironment),除非通过特定的API。 (2)Davik虚拟机还使用了垃圾回收(garbage collection)机制。这意味着,当虚拟机检测到一个变量、对象或者其他内存片段不再被使用时,就会把这些内存释放掉以备重用;它也能腾挪内存以提高空间使用效率。本地环境并不是这样工作的,它不期望内存块会被移来移去或者被自动释放。Android之所以这样设计,是因为开发者在开发程序的时候不必关心特定的CPU或者机器架构,也不必关心底层的内存管理。这通常都能工作得很好,除非要与本地系统交互比如OpenGL。OpenGL作为本地系统库直接运行在硬件上;没有虚拟机,也没有垃圾回收或内存压缩。 六、OpenGL 怎样平滑地从一个点向另外一个点混合颜色 线性插值 直线:长度做线性插值 三角形:面积做线性插值 直线颜色线性插值,示例如下 直线起始点坐标(-0.5,0),终点坐标(0.5,0) 片段着色器代码如下: precision mediump float; varying vec4 v_Color; void main(){ if(gl_FragCoord.x>-0.5 && gl_FragCoord.x < 0.5){ gl_FragColor.r = v_Color.r*(gl_FragCoord.x +0.5); gl_FragColor.g = v_Color.g*(gl_FragCoord.x +0.5); gl_FragColor.b = v_Color.b*(gl_FragCoord.x +0.5); } else { gl_FragColor =v_Color; } } 绘制直线如下: glDrawArrays(GL_LINES, 18, 2)

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

293 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传