OpenGL编程指南2D部分【下】

来源:互联网 发布:奶瓶linux系统下载 编辑:程序博客网 时间:2024/05/21 06:20

自己用Laravel写的小博客和CSDN的博客以后同步更新:
OpenGL编程指南2D部分【下】

4. 颜色、像素和帧缓存

颜色

OpenGL需要RGB/sRGB格式的颜色
Fragment shader中指定颜色为顶点颜色,会使用高洛德着色填充区域

光栅

处于vertex shader和fragment shader之间
处理每个像素的buffer

多重采样

一种简洁的实现抗锯齿的方法
需要程序提供一个额外的多重采样缓存,使用时无法同时使用点线面平滑处理
可以通过glGetIntererv(GL_SAMPLE_BUFFERS)检测缓存是否存在
需要提供采样次数,最大次数通过

fragment shader中的sample关键字不知道怎么用,加上即黑屏。
glMinSampleShading使用起来并没有什么效果

缓存

OpenGL有颜色缓存,深度缓存和模板缓存,共同构成帧缓存
通过glClear[type]设置缓存清除默认值
通过gl[type]Mask来决定那些缓存可以写入

测试

一个像素点需要经过:
1. 裁剪测试
2. 多重采样操作
3. 模板测试
4. 深度测试
5. 混合
6. 抖动
7. 逻辑操作

裁剪是控制一个矩形,只能绘制在这个矩形当中。
使用glScissor设置矩形,glEnable开启测试

默认多重采样不考虑alpha,通过glEnable开启特殊模式可以考虑alpha

模板测试通过glStencilFunc设置测试的标准值和测试操作
通过glStencilOp设置测试完成的操作
可以先将测试设为一定通过,然后设置测试完成之后修改值,绘制一个模板
然后将测试设为正常值,绘制图像

深度测试默认可以控制顶点绘制时后面的点不会覆盖前面的点
可以通过glDepthFunc控制测试操作类型

混合是两个不透明颜色如何绘制在一个点上
表达式:Cr = S * Cs + D * Cd
通过glBlendFunc控制混合方式
通过glBlendColor设置混合颜色常量
通过glBlendEquation控制计算符号

抖动是一种半色调的提高表现质量的方法

逻辑操作可以将颜色与当前帧缓存里面的颜色进行操作
产生新的颜色,通过glLogicOp来控制操作方法

多边形偏移

如果给多边形画边框,因为深度相同,但是光栅对于多边形和线条操作不同
会导致边框若隐若现,通过glEnable打开偏移功能,glPolygonOffset设置
可以将多边形或者线条的深度偏移一下,保证绘制正常

遮挡查询

通过渲染一个框架,确认这个框架是否可见来决定是否渲染框架中的多边形
达到节省渲染资源的目的,过程如下:

  1. 建立查询ID
  2. 开始查询
  3. 绘制多边形
  4. 结束查询
  5. 查看结果

通过glGenQueries建立ID,调用glBeginQuery开始查询,调用glEndQuery结束查询
在通过glGetQueryObjectiv来查找查询结果

条件渲染

通过遮挡查询的结果可以通过glBeginConditionalRender来继续绘制
如果查询不成功则绘制命令无效
通过glEndConditionalRender结束条件绘制
可以提高效率

逐图元抗锯齿

通过glHint设置抗锯齿的模式,开启blend设置blendfunc即可。

帧缓存

显示在屏幕上帧缓存只有一个,不过可以自己创建帧缓存以达到离屏渲染。

可以通过glGenFramebuffer来创建帧缓存。相对的有glBindFramebuffer和glDeleteFrameBuffer。
通过glGenRenderbuffer来创建渲染缓存。相对的有glBindRenderbuffer和glDeleteRenderBuffer。
有了渲染缓存之后要对它创建存储空间,通过glRenderbufferStorage[Multisample]
可以将渲染缓存绑定到帧缓存中作为任意缓存。

帧缓存可以设置为绘制或者读取模式,方便帧缓存之间拷贝数据。
glClearBuffer可以指定清除哪一个缓存。
glInvalidateFramebuffer可以删除帧缓存。

同时写入多个渲染缓存

通过设置将不同的fragment shader输出导入到不同渲染缓存实现
通过glBindFragDataLocation通知编译器将输出名称绑定到位置
编译完成后通过glGetFragDataLocation获取位置

设置绘制缓存

通过glDrawBuffer设置一个应该被写入的缓存
通过glReadBuffer设置一个应该被独处的缓存

双源混合

通过index=2的输出函数决定混合时所用的系数。

读取写入像素点

通过glReadPixels读取缓存中像素点
通过glClampColor将数据normalized
通过glBlitFrameBuffer在不同的缓存之间拷贝像素

5. 视图变换,剪切和反馈

基本的视图变换都是通过变换矩阵和向量相乘得到

为了方便平移操作,我们向量变为四位齐次向量

转换矩阵

平移矩阵:vmath::translate

缩放矩阵:vmath::scale

旋转矩阵:vmath::rotate (欧拉旋转)

透视投影:

vmath::frustum调整摄像机zoom和远近两个面

vmath::lookAt调整摄像机方向

正交投影:vmath::ortho

转换法向量

转换矩阵的逆的转置乘以法向量可得法向量的转换

OpenGL转换

glDepthRange告诉OpenGL深度的绘制范围

glViewport告诉OpenGL视口的大小

z轴精度

精度会随着z轴变大逐渐减小

用户剪切

提供的一种让用户自主切割图元和frustum相交的地方

变换反馈

可通过把vertex shader计算之后的结果存入buffer来实现反馈

通过把反馈的数据继续送入vertex shader可以实现gpu自动控制的粒子效果

6. 纹理

纹理类型

纹理有多种不同的类型,不同类型的纹理应该使用不同的sampler

创建纹理

  1. 通过glGenTexture创建纹理对象
  2. 通过glBindTexture绑定对象至一个绑定点
  3. 通过glActiveTexture将当前绑定的对象激活至某个纹理
  4. 通过glTexStorage[]将给对象分配纹理空间
  5. 通过glTex[]Image[]给对象纹理数据
  6. 通过glUniform1i分配纹理序号给sampler
  7. 在shader中使用texture获取texel

内部类型

opengl内部使用来存储纹理数据的方式,
可以是某种压缩类型。

外部类型

提供给opengl纹理数据的类型,
可以是某种打包类型。

向opengl提供数据

直接提供:通过glTexSubImage。
间接提供:通过glTexSubImage将指针设置为0,并且绑定一个PIXEL_UNPACK_BUFFER。

从帧缓存读取

通过glCopyTexImage1D从帧缓存读取已经渲染完成的缓存内容

纹理对象

通过glGetTexImage从纹理对象中读取纹理数据
通过glPixelStorei决定opengl存储纹理数据的方式

取样器

一种用来方便从纹理中读取texel的工具
默认取样器效果比较好

压缩的纹理

通过使用glCompressedTexImage来使用压缩的纹理

过滤

经常的情况下,texture的点和屏幕的点并不是精准对应
所以需要filter来取样
线性取样比较平滑,最近取样比较锐利

mipmap

mipmap用来将texture分为多个精度,
在不同的距离,使用不同精度的map。
提高效率,优化表现。
使用glGenerateMipmap生成mipmap

高级texture函数

textureLod自定义mipmap层级
textureGrad自定义渐变
textureOffset提取texel时指定偏移
textureProj投影时对texel提取进行变换
textureQueryLod读取texel的mipmap信息
textureSize读取texture大小信息
textureGather读取四个取样点
以上函数还有各种组合版

点精灵

通过一个点完成对一个矩形的渲染,提高效率
通过glPointParameter来决定点精灵的样子

向纹理图渲染

删除帧缓存

附1. 遇到的坑

  • element_array_buffer的创建必须在VAO创建之后,不然会黑屏。

  • glVertexAttribPointer中的stride为0的时候表示数据紧密相邻,但是并不是说stride是数据间隔,当stride不为0时代表的两个点数据间隔的距离加上点数据的大小。

0 0
原创粉丝点击