OpenGL

九、OpenGL渲染技巧 - 深度测试&多边形偏移&裁剪&混合

2020-07-12  本文已影响0人  小山93

1. 深度测试

深度测试的目的是防止被其他面遮挡的面显示出来。开启深度测试后,会对新的片段进行测试,测试通过的片段放进深度缓冲区,不通过的则被丢弃。

1.1 深度

1.2 深度缓冲区

是一块内存区域,存储每一个像素点的深度值,一个像素只有一个深度。

1.3 深度测试

// 在绘制场景前,清除颜⾊缓存区,深度缓冲
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 开启深度测试
glEnable(GL_DEPTH_TEST);
// 关闭深度测试
glDisable(GL_DEPTH_TEST);

// 打开/关闭深度缓冲区写入 ,GL_FALSE: 关闭写入 GL_TRUE:打开写入
glDepthMask(GLBool value);

// 指定深度测试判断模式,默认GS_LESS,当前深度值 < 存储深度值时通过
glDepthFunc(GLEnum mode);
深度测试判断模式.png

1.4 甜甜圈开启深度测试

上篇博客中的甜甜圈案例

  // 开启深度测试
    glEnable(GL_DEPTH_TEST);
    
    //5.绘制
    torusBatch.Draw();
    
    // 关闭深度测试
    glDisable(GL_DEPTH_TEST);
开启深度测试后的甜甜圈.gif

现在甜甜圈的展示,已经非常好了!
其实开启了深度测试后,我们甚至不需要使用背面剔除功能。因为深度测试的原理是一个像素内只绘制离观察者最近的图形图像。甜甜圈的背面离观察者远,自然不会绘制。

1.5 深度测试存在 Z-Fighting / Z闪烁 / Z冲突 的问题

// 使用多边形填充模式
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// 设置平面着色器,颜色为绿色
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
// 绘制
pBatch->Draw();

// 使用多边形线框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//设置线条宽度
glLineWidth(2.5f);
// 设置平面着色器,颜色为黑色
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
// 绘图
pBatch->Draw();

// 复原原本的设置
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
Z冲突效果.gif

1.6 Z-Fighting / Z闪烁 解决方案

// 1. 开启多边形偏移
glEnable(GL_POLYGON_OFFSET_FILL)
// 2. 关闭多边形偏移
glDisable(GL_POLYGON_OFFSET_FILL)
参数列列表: 
GL_POLYGON_OFFSET_POINT   对应光栅化模式: GL_POINT
GL_POLYGON_OFFSET_LINE    对应光栅化模式: GL_LINE
GL_POLYGON_OFFSET_FILL    对应光栅化模式: GL_FILL

// 2. 设定偏移量(一般情况下,设置-1, -1)
glPolygonOffset(Glfloat factor,Glfloat units)

上面金字塔案例中,增加如下修改:

// 设置偏移值
glPolygonOffset(-1.0f, -1.0f);
// 开启多边形偏移
glEnable(GL_POLYGON_OFFSET_LINE);

...

// 绘制后,关闭多边形偏移
glDisable(GL_POLYGON_OFFSET_LINE);

增加偏移值后的效果如下:


开启多边形偏移的金字塔.gif

1.7 Z-Fighting / Z闪烁 预防方案

2. 裁剪测试

//1 开启裁剪测试 
glEnable(GL_SCISSOR_TEST);
//2.关闭裁剪测试 
glDisable(GL_SCISSOR_TEST);
//3.指定裁剪窗⼝,  x,y:指定裁剪框左下角位置; width , height:指定裁剪尺⼨
void glScissor(Glint x,Glint y,GLSize width,GLSize height);

3 混合

// 启用颜色混合
glEnable(GL_BlEND);
// 关闭颜色混合
glDisable(GL_BlEND);

3.1 混合方程式

Cf = (Cs * S) + (Cd * D)
Cf :最终计算参数的颜⾊
Cs : 源颜⾊
Cd :⽬标颜色
S:源混合因⼦子
D:⽬标混合因⼦

// 选择混合方程式
void glbBlendEquation(GLenum mode);

// 设置混合因⼦, S:源混合因子 D:⽬标混合因⼦
void glBlendFunc(GLenum S,GLenum D); 
// 常见的混合因子
void glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

// 设置混合因⼦及Alpha因⼦
// strRGB: 源颜⾊的混合因子 
// dstRGB: ⽬标颜色的混合因子 
// strAlpha: 源颜⾊的Alpha因子 
// dstAlpha: ⽬标颜色的Alpha因⼦
void glBlendFuncSeparate(GLenum strRGB,GLenum dstRGB ,GLenum strAlpha,GLenum dstAlpha);

// 设置常量混合颜色,默认黑色
void glBlendColor(GLclampf red ,GLclampf green ,GLclampf blue ,GLclampf alpha );
可选择的混合方程式.png 混合因子.png
上一篇下一篇

猜你喜欢

热点阅读