位置: 编程技术 - 正文

OpenGL编程逐步深入(四)Shaders(简述opengl的编程步骤)

编辑:rootadmin

推荐整理分享OpenGL编程逐步深入(四)Shaders(简述opengl的编程步骤),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:简述opengl的编程步骤,opengl编程基础,opengl 编程,opengl gpu编程,opengl编程基础,opengl 编程,opengl编程基础,opengl编程实例,内容如对您有帮助,希望把文章链接给更多的朋友!

OpenGl 中的 Shader在一些中文书籍或资料中都被翻译为“着色器”, 单从字面意思也看不出Shader到底是什么,Shader实际上就是一段代码,用于完成特定功能的一个模块。Shader分为Vertex Shader(顶点着色器)和Pixel Shader(像素着色器)两种,其中Pixel Shader在本文中又被称为Fragment Shader(片段着色器)

准备知识

从本节开始我们將使用Shader来实现游戏中的各种特效,Shader是现代3D图形学中重要的渲染技术。从某种程度上,你可以抱怨这种做法是比较落后的,因为固定渲染管道(fixed function pipeline)提供的3d功能本来只需要开发人员指定配置参数(例如光照属性、旋转值)就可以了,现在都要通过编写Shader代码来实现。然而这种可编程方式为编写程序提供了更大的灵活性和创新性。

OpenGl的可编程管道可以由下图直观的表达:

顶点处理器(vertex processor)负责执行每个通过管道的顶点的vertex shader(数量取决于调用绘图函数是传入的参数),Vertex shaders并不知道渲染图元的拓扑结构(是绘制四边形还是三角形?),因此顶点处理器(vertex processor)是必须的。每个顶点只进入顶点处理器一次,经过变换后沿着管道执行下一步处理。(注:所谓的管道是指从顶点输入到渲染到屏幕上经历的整个过程)

接下来是几何处理器(geometry processor)阶段。在这个阶段,一组连续的顶点如何构成图形的信息将会提供给Shader。这使得我们需要考虑除了顶点自身之外的额外信息。几何处理器(geometry processor)能够改变调用绘图函数时指定的拓扑结构(点、线、三角形等),例如你可以將它用在一组点上,將原指定拓扑结构生成的四边形变成两个三角形(公告牌技术的应用)。此外,你还可以让几何处理器(geometry processor)忽略多个指定的点,让这些点以调用绘图函数时指定的拓扑结构来绘制图形。

管道中的下一阶段为裁剪阶段(Clipper),这是一个任务较为简单的固定功能单元,会裁剪掉上一节教程中的正方形以外的图形元素,除此之外Z轴方向上的近裁剪面和远裁剪面以外的部分也会被裁剪掉。能够映射到屏幕的顶点不会被裁剪,光栅化程序会根据绘图函数指定的拓扑结构(三角形、四边形等)將图形渲染在屏幕上。例如:拓扑结构指定为三角形时光栅化程序会找到三角形内部的所有点并对它们进行渲染。对于每个点光栅化程序会调用片段处理器。在这里你可以通过对纹理采样(或者使用其他技术)确定像素的颜色。

上面的三个可编程阶段是可有可无的,如果不对它们绑定Shader,一些默认的功能将会被执行。

Shader的创建和c/c++程序非常相似,首先编写Shader代码,然后确保它在你的程序中能正确执行。可以在程序中使用字符数组来存储Shader代码或者將Shader写在一个外部的文件中,然后在程序中加载它。接着把这些Shader全部的编译成Shader对象,最后使用链接器將这些Shader链接到一个单独的program 对象加载到GPU中。链接Shader对象使得驱动能够对这些Shader进行裁剪并根据它们的关系做优化处理。

项目配置

1.在前几节项目解决方案中新建控制台应用。 2.在项目上点击右键选择属性,將配置属性->常规->项目默认值->字符集设置为“使用多字节字符集”。 在配置属性->VC++目录下的包含目录中添加$(SolutionDir)Include和$(SolutionDir)Includeassimp在库目录中添加$(SolutionDir)Lib 在配置属性->链接器->输入->附加依赖项中添加freeglut.lib、glew.lib、assimp.lib

程序代码

清单1.主程序 tutorial.cpp代码

代码解读

这里我们创建一个Program对象,你可以把它是Shader的容器,我们将会把所有的Shader对象链接到这个Program对象中。

我们通过glCreateShader函数的调用创建两个Shader对象,其中一个Shader类型为GL_VERTEX_SHADER(Vertex Shader),另外一个为GL_FRAGMENT_SHADER(Fragment Shader)。 Shader对象用于维护我们编写的Shader代码。

在编译Shader对象之前我们必须指定它的源码,glShaderSource 函数以Shader对象作为参数,提供了一种灵活的方式指定Shader源码。源码可以分布在多个字符数组中,你需要提供一个存放这些字符数组地址的数组的指针和一个存放每个数组长度的数组的指针。为了简单起见,我们使用一个字符数组存放所有的Shader源码和只有一个元素的GLint数组存放字符数组的长度。 第二个参数指定这两个数组元素个数。

调用该函数编译Shader对象。

OpenGL编程逐步深入(四)Shaders(简述opengl的编程步骤)

这段代码用于输出Shader对象编译出错时的错误信息。

將编译后的Shader对象附加到之前创建的Program对象中,非常类似于在makefile文件中添加需要链接的对象列表。因为我们没有一个makefile文件来效仿gnu make的行为,所以只能调用函数的方式为链接处理做准备。

在所有的Shader对象经过编译并把它们附加到Program对象之后,调用glLinkProgram来链接它们。需要注意的是,完成Program对象的链接后,可以调用glDetachShader 和glDeleteShader 函数来解除附加的Shader对象。OpenGl驱动中维护着它所生成的大多数对象的引用计数,如果一个Shader对象创建之后又被删除,驱动程序去把它去除,但是如果它被附加到Program对象中,调用glDeleteShader 后驱动程序仅仅会把它标记为删除,你还需调用glDetachShader 將它的引用计数置为0,然后它才会被删除。

注意:我们检测Program对象相关错误(例如链接错误)和检测Shader对象错误调用的函数有些不同,使用glGetProgramiv 代替glGetShaderiv ,使用glGetProgramInfoLog代替glGetShaderInfoLog 。

看到这段代码,你可能会问为什么已经成功链接Program对象后还要调用glValidateProgram来校验该对象。所不同的是链接错误检测针对的是Shader对象的合并,而该函数是检测Program对象在该管道状态下是否能正确执行。

最后调用调用上面这个函数,安装Program对象作为当前渲染状态的一部分。这个Program对象会影响所有绘图函数的调用,直到你替换它或使用glUseProgram指定参数为NULL来显式的禁用它。

清单2.shader.vs代码

告诉编译器GLSL版本为3.3,如果编译器不支持將会抛出异常。

这段代码在Shader中声明一个顶点特定属性(vertex specific attribute)Position,它是由3个float类型构成的向量。顶点特定(vertex specific)意味着在GPU调用每一个shader时,在缓冲区中的新顶点的值会被提供。声明的第一部分layout (location = 0),创建属性名和缓冲区中属性的绑定。这样做是为了防止我们的顶点中有多个属性(位置、法线、纹理坐标等)。我们需要让编译器知道顶点中的哪个属性必须映射到shader中声明的属性。有两种做法,我们可以像上面代码一样不明确的设置(指定为0)。如果这样我们可以在程序中使用一个硬编码的值(即调用glVertexAttributePointer函数时的第一个参数值)。或者我们可以不管它(即上面语句直接写成‘in vec3 Position’),然后在运行时使用glGetAttribLocation从程序中查询该location 。这时我们需要將返回值用在glVertexAttributePointer 函数参数中来取代硬编码方式。这里我们选择较为简单的方式,但是在更复杂的程序中最好让编译器决定属性的索引并且在运行时查询它们。这使得把Shader从多个源文件整合起来变的更简单,而无需把它们调整到缓冲区布局中。

你可以通过把多个Shader对象链接来创建你自己的Shader,然而在每个着色阶段(VS,GS,FS)只能有一个main函数作为Shader的入口点。

这里我们通过硬编码方式对传过来的顶点位置进行变换。把X/Y的值减半,Z的值保持不变,gl_Position是一个特殊的内置变量应该包含齐次的顶点坐标位置。光栅化程序会找到这个变量,并使用它作为屏幕空间的位置。使X/Y值减半意味着我们能看到的三角形的大小将是前面教程中的1/4。需要注意的是我们把W的值设为1,这对三角形的正确显示是至关重要的。投影从3D到2D实际上是在两个独立的阶段完成。首先你需要把所有顶点乘上投影矩阵,在顶点到底光栅化程序之前,GPU会为位置属性自动执行所谓的“透视分割”。这意味着所有的组件都会除以gl_Position 的W组件值。在本教程中我们还没有在vertex shader中做任何投影,但是透视分割(perspective divide)阶段不可缺少。

清单3. shader.fs代码

通常片段着色器(fragment shader)的作用是决定像素的颜色。此外,fragment shader可以完全丢弃像素或改变其Z值(将会影响随后的Z test结果)。在该案例中,屏幕图形输出的颜色由上面的变量决定,包含四个组件分别为R、G、B、A(alpha,即透明度),设置到这个变量中的值将会被光栅化程序接收并写入到帧缓冲区。

在前面的教程中没有用到片段着色器,所有绘制的图形默认都是白色,这里通过FragColor 设置为红色。

编译运行程序

你可以看到一个红色的三角形显示在屏幕中间。

OpenGL--纹理贴图基础 理论基础纹理贴图:通俗地讲就是可以把我们读取的纹理加载到图元表面的一种技术,这样大大的提高了图像的表现质量。实例代码//读取tga格式图片/*t

关于模型视图变换的一些理解 OpenGL可以通过glMatrixMode(GL_MODELVIEW)来修改模型视图矩阵的值。模型视图矩阵包含模型变换和视图变换,在OpenGL中经常将这两种变换混在一起进行讨论,这

OpenGL版本查看 本文代码摘自如何查看OpenGL版本?gl和glut库提供了版本查看函数,只需要调用就可以了:#includeWindows.h#includestdio.h#includeGL/glut.hintmain(intargc,char**argv){glutInit

标签: 简述opengl的编程步骤

本文链接地址:https://www.jiuchutong.com/biancheng/369548.html 转载请保留说明!

上一篇:用Quadro卡带Geforce卡实现非SLI多显卡多显示器协同绘制(卡带测评)

下一篇:OpenGL--纹理贴图基础(opengl纹理贴图正方体六个面)

  • 供暖服务费增值税怎么算
  • 城建税和教育费附加可以税前扣除吗
  • 错账更正方法有哪几种
  • 无形资产多摊销了怎么办
  • 金蝶固定资产折旧怎么修改
  • 房产折旧计算方法 举例
  • 项目清算组
  • 公司支付员工工伤赔偿怎么做账
  • 市场开发费用会计分录
  • 装饰设计费计入什么科目
  • 一次还本付息债券到期收益率
  • 发票报销哪些能用专票
  • 废品计入哪个科目
  • 多转出的进项税能否转回
  • 同一套房
  • 补贴与工资薪金一起发放,属于福利费,还是纳入工资薪金总额税前扣除?
  • 含税价标志有无影响
  • 计提个人负担的社会保险费分录
  • 资本增值是什么
  • 走物流的货物如何收费
  • 企业收取的延期付款利息需要征消费税和增值税
  • 如何关闭windows10资讯
  • 高新技术企业改革
  • win7系统我的电脑图标不见了
  • 间接费用是什么费用
  • linux系统的
  • 税额差异会计分录
  • 没有取得发票的成本可以税前扣除吗
  • 补缴以前月份的个人所得税
  • 前端数据统计图
  • 企业接受现金捐赠如何开具发票
  • 补付转账支票会退回吗
  • 可解释深度学习:从感受野到深度学习的三大基本任务:图像分类,语义分割,目标检测,让你真正理解深度学习
  • 大二一学期学分多少合适
  • 用ipconfig/all命令不能显示
  • 矿山征收
  • 支出和收入怎么算呀
  • 国际货运代理公司个人货物
  • 银行账户管理的直接责任人是共享中心核算会计
  • python2.7 协程
  • 公司向银行贷款还不上会怎么样
  • 个体户税务分几种
  • 用友会计科目增加二级
  • sqlserver2016使用方法
  • 利息收入为负数的原因
  • 人力资源劳务外包需要什么资质证书
  • 固定资产清理的金额怎么算
  • 月末结存材料的实际成本例题
  • 商场活动经费预算
  • 买公司宿舍有保障吗
  • 以前年度损益调整借贷方向
  • 建筑企业成本核算方法
  • 融资租赁资产承租人的账务处理
  • 在建工程转长期待摊费用是什么意思
  • 外埠存款账务处理方法
  • 产品成本核算有多条原则和要求
  • xp系统打印任务一闪就没有了
  • 电脑找不到关机选项了怎么关机
  • win10rs2是哪个版本
  • mac锁定快捷键
  • 64位下无法运行32位程序的解决方法 提示未指定提供程序,也没有指派的默认提供程序
  • win10一年更新一次
  • linux doc
  • linux常用命令cat
  • windows7出现错误恢复怎么办
  • win10本地连接怎么改名称
  • win8.1升级到win10
  • win7系统怎么把其他盘空间给c盘
  • 老生常谈的近义词
  • android2d游戏开发
  • UNIX sh(Bourne Shell)脚本里面使用数组的两种方法
  • Intent and Intent Filters
  • 有道词典下载安装
  • 怎样学好js中的逻辑
  • 加油站怎么收税
  • 江苏社保退工办理流程
  • 购买方销售方什么意思
  • 深圳市保安证办理流程
  • 济南高新发展公告
  • 江苏几个地级市几个县级市
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设