sxaudq0 2020-02-23
1、OpenGL使用的是RGB颜色空间,例如三个颜色分量各占8位,那么就说这个颜色值色深24,能够表示2^24中颜色。
2、多重采样是基于采样的抗锯齿技术,有OGAA(ordered grid anti-sliasing)、SGAA(sparse grid anti-aliasing)、MSAA(multi-sampling anti-aliasing)、CSAA(coverage sampling anti-aliasing)等众多实现方式。fragment shader中有gl_SamplePosition、gl_SampleID等内置变量与之相对应的相关信息,限定符sample修饰fragment shader的输入变量时,会在同一个像素上执行多次,每次输出不同的样本位置信息。sample shader 专门用于描述逐样本执行的shader。如下:
#version 330 core
sample in vec4 color;
out vec4 fragColor;
void main()
{
fragColor = color;
}
3、片元的测试与操作
1)剪切测试(scissor test)
是片元可见性判断的第一个附加测试。glEnable(GL_SCISSOR_TEST)启用该测试,void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)将绘制区域限制在该函数参数所形成的矩形内。默认情况下,剪切矩形与窗口大小一致并且是关闭的。(与视窗的绘制限制不同,视窗的不会限制屏幕的清除操作)
2)多重采样操作
默认情况下多重采样计算片元覆盖率不会考虑alpha,开启一下功能则会将alpha纳入参考。
.GL_SAMPLE_ALPHA_TO_COVERAGE 使用片元的alpha来聚散最后采样覆盖率,并且这个过程与硬件实现无关。
.GL_SAMPLE_ALPHA_TO_ONE 将片元的alpha值设置为最大值,然后时候这个值进行覆盖率计算。
.GL_SAMPLE_COVERAGE 将使用glSampleCoverage设置的数值,与覆盖率计算结果进行 与 操作。
.GL_SAMPLE_MASK 使用glSampleMaski设置一个精确的位掩码来计算和表达覆盖率,与片元的采样覆盖值进行 与 操作。这个值也可以通过fragment shader 的 gl_SampleMask进行设置。
3)模板测试(stencil test)
使用模板测试需要在创建窗口时请求生成模板缓冲,使用glStencilFunc 与 glStencilOp 设置测试的mask与比较方法。
void glStencilFunc(Glenum func, GLint ref, GLuint mask)//func是比较方法的枚举,ref是参考值,mask是测试掩码
void glStencilSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)//允许我们为多边形的正面和背面分别设置模板参数
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
void glStencilSeparateOp(GLenum fail, GLenum zfail, GLenum zpass)
4)深度测试(depth test)
使用深度测试需要在创建窗口时请求生成深度缓冲,启用GL_DEPTH_TEST。
void glDepthFunc(GLenum func)//可以选定比较深度的方法,GL_LESS等
比如需要给物体的边框加亮显示,那么可以正常的绘制一遍物体,然后使用glPolygonMode设置为点线模式绘制一遍物体,但是因为这两种绘制模式下的光栅化方法并非完全一致,所以可能造成深度冲突(斑驳,stitching),有一种通常的处理方法就是为它们加一个适当的偏移值,对应于glEnable的参数是GL_POLYGON_OFFSET_POINT、GL_POLYGON_OFFSET_LINE、GL_POLYGON_OFFSET_FILL中的一种,与下面这个函数配合确定偏移值。
void glPolygonOffset(GLfloat factors, GLfloat units)//offset = m*factor + r*units
m是多边形最大深度斜率(光栅化的时候得到),r是深度值最小可识别间隔。m的意义是在遍历多边形时,z相对于x或y坐标上的变化关系式
5)融合(blending)
一个片元通过了上面的所有测试,就可以与当前的颜色缓冲相对应的位置按照指定的方式进行内容的合并,这称之为融合。
void glBlendFunc(GLenum srcfactor, GLenum destfactor)//src是当前处理片元,dest是缓冲中已经存在的数据
void glBlendFunci(GLuint buffer, GLenum srcfactor, GLenum destfactor)//buffer是缓冲id,多缓冲绘制时候使用
void glBlendFuncSeparate(GLenum srcRGB, GLenum destRGB, GLenum srcAlpha, GLenum destAlpha)//功能与上面的相同,只是指定了src与dest的色值,设置的是所有可绘制的缓冲的混合参数
void glBlendFuncSeparatei(GLuint buffer, GLenum srcRGB, GLenum destRGB, GLenum srcAlpha, GLenum destAlpha)
上面的方法指定的都是混合是参与计算的数值比例等,下面的将是指定计算方法
void glBlendEquation(GLenum mode)
void glBlendEquationi(GLuint buffer, GLenum mode)
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
void glBlendEquationSeparatei(GLuint buffer, GLenum modeRGB, GLenum modeAlpha)
计算方式有GL_FUNC_ADD(默认方式)、GL_FUNC_SUBTRACT、GL_REVERSE_SUBTRACT、GL_MIN、GL_MAX等
6)抖动(dithering)
对于颜色位面数目较小的系统,可以通过对图像中的颜色进行抖动来提升颜色的分辨率,代价是损失一定的空间分辨率(???)。抖动是与硬件相关的,OpenGL只提供了开启与关闭没有其它操作空,GL_DITHER。
7)逻辑操作
这是片元的最后一个逻辑操作,包括或(OR)、异或(XOR)、反转(INVERT),作用于src与dest。这种操作对于位块传输类型系统非常有用,因为它们的主要的图形操作就是讲某一处矩形数据拷贝到另外一处。逻辑操作是对输入数据与已有数据做一次逻辑操作来得到新的目标数据。可以通过传递GL_COLOR_LOGIC_OP参数开启它,默认状态值是GL_COPY。
void glLogicOp(Glenum opcode)//GL_AND、GL_OR、GL_NAND、GL_NOR......
但是对于浮点型缓冲或者是sRGB格式缓冲,逻辑操作将会被自动忽略。
4、渲染查询
为了尽可能的提高性能,尽可能的先判断几何物体的可见性再将它们的几何信息送入渲染管线,可以使用遮挡查询的方法判断几何物体的可见性,这一步在深度测试值后完成。算法的大致为先渲染一个精简版的几何物体测试可见性,而且这个渲染过程尽可能简单,只要不影响可见性的测试其它所有功能都可以关闭,通过后再渲染真实的几何物体。
(1)为查询生成ID,调用glBeginQuery(ID),开始查询
(2)渲染精简版的几何物体,调用glEndQuery(ID)完成查询
(3)获取深度测试通过的样本数目
void glGenQueries(GLsizei n, GLuint* ids)//生成n个查询id,存储到ids中
void glBeginQuery(GLenum target, GLuint queryid)//target是需要查询的信息GL_SAMPLES_PASSED等表示一类渲染结果的枚举
void glEndQuery(GLenum target)
void glGetQueryObjectiv(GLenum queryid, GLenum pname, GLint* params)//pname表示需要获取查询状态如GL_QUERY_RESULT,params用于存储获取的结果
void glGetQueryObjectuiv(GLenum queryid, GLenum pname, GLint* params)
void glDeletQueries(GLsizei n, GLuint* ids)
5、条件渲染
对于上面的渲染查询,OpenGL需要停止几何体与片元的处理来处理查询和将这些结果反馈给应用程序。目前,可用使用条件渲染来优化这一性能损失,根据查询结果确定接下来要做什么。
void glBeginConditionalRender(GLuint id, GLenum mode)//mode指定了如何使用查询结果GL_QUERY_WAIT、GL_QUERY_NO_WAIT、GL_QUERY_BY_REGION_WAIT、GL_QUERY_BY_REGION_NO_WAIT
void glEndConditionRender()
6、简单的反走样
OpenGL会通过像素块所覆盖的范围来就散每个片元的覆盖值,然后与Alpha相乘,接着就能进行混合的操作。可以使用glHint来控制图像的反走样,不过这个方法与硬件实现相关。
void glHint(GLenum target, GLenum hint)
1)线段反走样
首先需要开启融合状态。
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_LINE_SMOOTH_HINT, gl_DONT_CARE);
2)多边形反走样与线段反走样类似