OpenGL之裁剪与颜色混合

裁剪

  • 在OpenGL中提⾼渲染的⼀种方式:只刷新屏幕上发生变化的部分,OpenGL 允许将要进⾏行渲染的窗⼝只去指定⼀个裁剪框;
  • 基本原理:⽤于渲染时限制绘制区域,通过此技术可以再屏幕(帧缓冲)指定一个矩形区域。启用剪裁测试之后,不在此矩形区域内的⽚元被丢弃,只有在此矩形区域内的片元才有可能进⼊帧缓冲,因此实际达到的效果就是在屏幕上开辟了一个⼩窗口,可以再其中进行指定内容的绘制;
  • 裁剪函数:
   // 开启裁剪测试
   glEnable(GL_SCISSOR_TEST);
   
   // 关闭裁剪测试
   glDisable(GL_SCISSOR_TEST);

   // 指定裁剪窗⼝:x,y指定裁剪框左下角位置;width、height:指定裁剪尺⼨
   void glScissor(Glint x,Glint y,GLSize width,GLSize height);
  • 裁剪区域(平⾏投影):就是视⼝矩形区域的最⼩最大x坐标(left,right)和最⼩最大y坐标 (bottom,top),⽽不是窗⼝的最⼩最大x坐标和y坐标,通过glOrtho()函数设置,这个函数还需指定最近最远z坐标,形成⼀个⽴体的裁剪区域。

  • 具体代码如下:

#include "GLTools.h"
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif

// 召唤场景
void RenderScene(void) {
    // 设置清屏颜色为蓝色
    glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 1.现在剪成小红色分区
    // (1)设置裁剪区颜色为红色
    glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    // (2)设置裁剪尺寸
    glScissor(100, 100, 600, 400);
    // (3)开启裁剪测试
    glEnable(GL_SCISSOR_TEST);
    // (4)开启清屏,执行裁剪
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 2.裁剪一个绿色的小矩形
    // (1).设置清屏颜色为绿色
    glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
    // (2).设置裁剪尺寸
    glScissor(200, 200, 400, 200);
    // (3).开始清屏执行裁剪
    glClear(GL_COLOR_BUFFER_BIT);
    
    // 关闭裁剪测试
    glDisable(GL_SCISSOR_TEST);
    
    //强制执行缓存区
    glutSwapBuffers();
}

void ChangeSize(int w, int h) {
    // 保证高度不能为0
    if(h == 0)
        h = 1;
    
    // 将视口设置为窗口尺寸
    glViewport(0, 0, w, h);
}

// 程序入口
int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(800,600);
    glutCreateWindow("OpenGL Scissor");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);
    glutMainLoop();
    
    return 0;
}

颜色混合

一、混合概念解析

  • OpenGL 中的颜色混合就是将通过各种测试准备进入帧缓冲的片元(源片元)与帧缓冲中的原有片元(目标片元)按照设定的比例加权计算最终片元的颜色值。新片元不一定是直接覆盖缓冲区中的源片元。
  • OpenGL 渲染时会把颜色值存在颜色缓存区中,每个⽚段的深度值也是放在深度缓冲区。当深度缓冲区被关闭时,新的颜色将简单的覆盖原来颜色缓存区存在的颜⾊色值,当深度缓冲区再次打开时,新的颜色片段只是当它们⽐原来的值更接近邻近的裁剪平面才会替换原来的颜⾊片段
  • ⽬标颜⾊:已经存储在颜色缓存区的颜色值;
  • 源颜色:作为当前渲染命令结果进入颜色缓存区的颜色值;

二、混合方式

普通混合
  • 用于单纯的将两个图层重叠时进行颜色混合,这种混合并不能解决颜色的混合。在固定着色器和可编程着色器都可以使用这种开关的方式;
   // 开启颜色混合
   glEnable(GL_BlEND);
   // 关闭颜色混合
   glDisable(GL_BlEND);
混合因子
  • 用于处理类似滤镜效果的场景,简单描述就是将需要处理的图片颜色和图片上覆盖的半透明颜色进行混合,即两组颜色混合,此时如果只是单纯的开关方式,已经不能满足我们的需求,需要借助混合方程式,来实现两组颜色的混合。一般是在可编程着色器中片元着色器中使用;
   // 开启
   glEnable(GL_BlEND);
   // 设置混合因子--默认值是 GL_SRC_ALPHA 和 GL_ONE_MINUS_SRC_ALPHA
   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
   // 关闭
   glDisable(GL_BlEND);
  • 当混合功能被启动时,源颜⾊和⽬标颜⾊的组合⽅式是混合⽅程式控制的。在默认情况下,混合⽅程式如下所示:(Cf :最终计算参数的颜⾊;Cs : 源颜⾊;Cd :⽬标颜色;S:源混合因⼦;D:⽬标混合因⼦)
    Cf = (Cs * S) + (Cd * D) // 默认混合方程式
  • 混合⽅程式的选择: 混合⽅程式
  • 设置混合因子:需要用到glBlendFunc(GLenum S,GLenum D)函数(S:源混合因子;D:⽬标混合因子);
  • 除了能使⽤glBlendFunc 来设置混合因⼦,还可以void glBlendFuncSeparate(GLenum strRGB,GLenum dstRGB ,GLenum strAlpha,GLenum dstAlpha);(strRGB: 源颜⾊的混合因⼦;dstRGB: ⽬标颜⾊的混合因⼦;strAlpha: 源颜⾊的Alpha因⼦;dstAlpha: ⽬标颜⾊的Alpha因⼦)
总结
  • 最终颜⾊是以原先的红⾊(⽬标颜色)与后来的蓝色(源颜色)进行组合。源颜⾊的alpha值越⾼高,添加的蓝⾊颜⾊成分越高,⽬标颜⾊所保留的成分就会越少。
  • 混合函数经常⽤于实现在其他一些不透明的物体前面绘制⼀个透明物体的效果。
  • 颜色混合使用逻辑代码:
void RenderScene(void) {
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   
    // 1.开启混合
    glEnable(GL_BLEND);
    // 2.开启组合函数 计算混合颜色因子
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    // 定义颜色
    GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
 
    // 3.使用着色器管理器
    // *使用 单位着色器
    // 参数1:简单的使用默认笛卡尔坐标系(-1,1),所有片段都应用一种颜色。GLT_SHADER_IDENTITY
    // 参数2:着色器颜色
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
    // 4.容器类开始绘制
    squareBatch.Draw();
   
    // 5.关闭混合功能
    glDisable(GL_BLEND);
    
    // 同步绘制命令
    glutSwapBuffers();
}

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/107314968