位置: 编程技术 - 正文

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纹理贴图正方体六个面)

  • 税务师报名入口官网2022
  • 会员退费怎么算
  • 实收资本印花税税率多少
  • 如何保证企业生存发展
  • 合伙企业每年费用
  • 税务发票上的二维码
  • 工程的管理费收入怎么算
  • 采购设备包含安装费用吗
  • 商业保险费可以在个人所得税税前扣除吗
  • 发生非正常损失的购进货物不准予抵扣的增值税
  • 回迁房项目的会计和税务处理
  • 汇票的票据行为有贴现吗
  • 以股权投资入股放高利贷违法吗
  • 资产已报废折旧怎么计算
  • 公司预支了然后来报销的帐怎么做?
  • 保费收入确认的条件
  • 银行客户专用回单分录
  • 购入包装物
  • 购买银行理财产品被骗怎么办
  • 软件企业涉税风险分析
  • 每月发放奖金的会计分录
  • 营改增的会计分录
  • 其他综合收益影响净利润吗
  • 购买加油卡能否开发票
  • 企业对外捐赠现金的会计处理
  • win11有哪些提升
  • 无发票 入账
  • php基础入门教程
  • 阿伦河在哪
  • SpringBoot+Vue实现文件上传下载功能
  • 印花税不足一元需要缴纳吗
  • 季报的利润表本月金额填的是当月数可以吗
  • laravel 实例
  • 复式记账法会计名词解释
  • 网上学电脑哪个软件好
  • mysql unique null
  • 罚款收入算是营收收入吗
  • 合并会计报表编制实例
  • 应付福利费算支出吗
  • 网上银行跨行转账手续费
  • 本月销售商品会计分录
  • 建筑企业的安全生产许可证由谁颁发
  • 材料暂估入库的账务处理
  • 质保金怎么做账
  • 发票开错没有作废可以红字冲销吗?
  • 购进货物的运费税率是从主吗
  • 金蝶计价方法在哪里
  • 视同销售但未收到钱怎么做账?
  • 金蝶暂存凭证怎样转正常凭证
  • 3个点专票和6个点专票区别
  • 金税盘技术维护费可以抵扣吗
  • 财务票子怎么粘
  • 分公司需要独立核算和报税吗
  • execve函数
  • mysql的日志
  • 因windowssystem32
  • haozipsvc.exe是什么
  • winctlad.exe - winctlad是什么进程
  • 没有推送windows11
  • vim显示中文乱码
  • ubuntu安装chrom
  • 如何使用朋友的山姆卡
  • win10一年更新几次
  • live updater
  • js如何使用
  • 如何删掉win7系统
  • javascript的面向对象
  • edittext弹出软键盘
  • python 读取数据库
  • jQuery插件能输出到控制台
  • 内容滑动切换效果怎么弄
  • android 自定义
  • python不同进制的整数之间可以直接运算
  • Python随机生成数字求最小的三个数字
  • 什么是总分机构汇总纳税
  • 安徽省低保查询入口官网
  • 内蒙古税务局发票认证
  • 国家税务网上办税平台
  • 河北省税务局稽查局领导班子
  • 复印店开什么发票
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设