视频特效学习03-OpenGL渲染技巧解析

2020-04-15  本文已影响0人  小破孩丫
学习目标:

1.渲染过程产生的问题

void setupRC(void){
    glClearColor(0.5, 0.5, 0.7, 1);
    shaderManager.InitializeStockShaders();
    viewFrame.MoveForward(10.0f);
    //创建“环”
    gltMakeTorus(torusBatch, .5f, .3f, 60, 30);
    
}
void renderScene(void){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    modelViewMatix.PushMatrix(viewFrame);
    
    GLfloat vColor[] = { 0.2f, 0.4f, 0.6f, 1.0f };
    //使用默认光源着色器
    //通过光源、阴影效果跟提现立体效果
    //参数1:GLT_SHADER_DEFAULT_LIGHT 默认光源着色器
    //参数2:模型视图矩阵
    //参数3:投影矩阵
    //参数4:基本颜色值
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vColor);
    modelViewMatix.PopMatrix();
    torusBatch.Draw();
    glutSwapBuffers();
}

2.油画渲染

3.正面&背面剔除

//召唤场景
void renderScene(void){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    modelViewMatix.PushMatrix(viewFrame);
    //开启背面剔除
    glEnable(GL_CULL_FACE);
    GLfloat vColor[] = { 0.2f, 0.4f, 0.6f, 1.0f };
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vColor);
    modelViewMatix.PopMatrix();
    torusBatch.Draw();
    glutSwapBuffers();
}

运行结果:


背面剔除后的结果.png

4. 深度测试

深度测试判断模式.png
 glEnable(GL_DEPTH_TEST);

运行结果:


深度测试结果.png

*5. ZFighting闪烁

ZFighting02.png

6. 窗口、视口、裁剪区域

裁剪核心代码:

void renderScene(void){
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    //裁剪成红色分区
    //1.设置裁剪区域的颜色
   glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
   //2.设置裁剪尺寸
   glScissor(100, 100, 600, 400);
   //3.开启裁剪测试
   glEnable(GL_SCISSOR_TEST);
   //4.开启清屏,执行裁剪
   glClear(GL_COLOR_BUFFER_BIT);
   
   //裁剪成绿色分区
   //1.设置裁剪区域的颜色
   glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
   //2.设置裁剪尺寸
   glScissor(200, 200, 400, 200);
   //3.开启裁剪测试
   glEnable(GL_SCISSOR_TEST);
   //4.开启清屏,执行裁剪
   glClear(GL_COLOR_BUFFER_BIT);
   //关闭裁剪区域
   glDisable(GL_SCISSOR_TEST);
   
   glutSwapBuffers();
}

7. 颜色混合

用数学公式来表达一下这个运算方式:
。则混合产生的新颜色可以表示为:

//Cf:最终计算参数的颜色
//Cs:源颜色
//S:源混合因子
//D:目标混合因子
Cf = (Cs * S) + (Cd * d)
//假设源颜色的四个分量(指红色,绿色,蓝色,alpha值)是(Rs, Gs, Bs, As)
//目标颜色的四个分量是(Rd, Gd, Bd, Ad),
//源因子为(Sr, Sg, Sb, Sa)
//目标因子为(Dr, Dg, Db, Da)
Cf = (Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)
OpenGL混合因子.png
常用混合函数
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
#include <stdio.h>
#include "GLShaderManager.h"
#include "GLTools.h"
#include <GLUT/GLUT.h>
GLBatch     squareBatch;
GLBatch     redBatch;
GLBatch     blackBatch;
GLBatch     blueBatch;
GLBatch     greenBatcch;
GLShaderManager shaderManager;
GLfloat blockSize = 0.2f;
GLfloat vVerts[] = { -blockSize, -blockSize, 0.0f,
    blockSize, -blockSize, 0.0f,
    blockSize,  blockSize, 0.0f,
    -blockSize,  blockSize, 0.0f};

//重塑函数
void changeSize(int w, int h){
    glViewport(0, 0, w, h);
}

//召唤场景
void renderScene(void){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    //定义4种颜色
    GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 0.5f };
    GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };
    GLfloat vBlue[] = { 0.0f, 0.0f, 1.0f, 1.0f };
    GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vRed);
    redBatch.Draw();
    
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vGreen);
    greenBatcch.Draw();
    
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vBlue);
    blueBatch.Draw();
    
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY,vBlack);
    blackBatch.Draw();
    
    //固定矩形的颜色
    shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
    squareBatch.Draw();
    
    //核心代码 颜色混合
    //1.开启混合
    glEnable(GL_BLEND);
    //2.开启组合函数 计算混合颜色因子
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
    glutSwapBuffers();
    
}

//设置渲染环境
void setupRC(void){
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    shaderManager.InitializeStockShaders();
    
    //绘制移动的矩形
    squareBatch.Begin(GL_TRIANGLE_FAN, 4);
    squareBatch.CopyVertexData3f(vVerts);
    squareBatch.End();
    
    //绘制4个固定矩形
    GLfloat vBlock[] = {
        0.25f, 0.25f, 0.0f,
        0.75f, 0.25f, 0.0f,
        0.75f, 0.75f, 0.0f,
        0.25f, 0.75f, 0.0f
    };
    redBatch.Begin(GL_TRIANGLE_FAN,4);
    redBatch.CopyVertexData3f(vBlock);
    redBatch.End();
    
    GLfloat vBlock1[] = {
        -0.75f, 0.25f, 0.0f,
        -0.25f, 0.25f, 0.0f,
        -0.25f, 0.75f, 0.0f,
        -0.75f, 0.75f, 0.0f
    };
    greenBatcch.Begin(GL_TRIANGLE_FAN,4);
    greenBatcch.CopyVertexData3f(vBlock1);
    greenBatcch.End();
    
    GLfloat vBlock2[] = {
        -0.75f, -0.75f, 0.0f,
        -0.25f, -0.75f, 0.0f,
        -0.25f, -0.25f, 0.0f,
        -0.75f, -0.25f, 0.0f
    };
    blueBatch.Begin(GL_TRIANGLE_FAN,4);
    blueBatch.CopyVertexData3f(vBlock2);
    blueBatch.End();
    
    GLfloat vBlock3[] = {
        0.25f, -0.75f, 0.0f,
        0.75f, -0.75f, 0.0f,
        0.75f, -0.25f, 0.0f,
        0.25f, -0.25f, 0.0f
    };
    blackBatch.Begin(GL_TRIANGLE_FAN,4);
    blackBatch.CopyVertexData3f(vBlock3);
    blackBatch.End();
    
}

//特殊键位函数
void specialKeys(int key, int x, int y){
    
    //每一步移动的距离
    GLfloat stepSize = 0.025f;
    //以左上角的坐标为参照
    GLfloat blockX = vVerts[0];
    GLfloat blockY = vVerts[7];
    
    if (key == GLUT_KEY_UP) {
        blockY += stepSize;
    }
    if (key == GLUT_KEY_DOWN) {
        blockY -= stepSize;
    }
    if (key == GLUT_KEY_LEFT) {
        blockX -= stepSize;
    }
    if (key == GLUT_KEY_RIGHT) {
        blockX += stepSize;
    }
    //边界处理
    if(blockX < -1.0f) blockX = -1.0f;
    if(blockX > (1.0f - blockSize * 2)) blockX = 1.0f - blockSize * 2;;
    if(blockY < -1.0f + blockSize * 2)  blockY = -1.0f + blockSize * 2;
    if(blockY > 1.0f) blockY = 1.0f;
    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize*2;
    
    vVerts[3] = blockX + blockSize*2;
    vVerts[4] = blockY - blockSize*2;
    
    vVerts[6] = blockX + blockSize*2;
    vVerts[7] = blockY;
    
    vVerts[9] = blockX;
    vVerts[10] = blockY;
    squareBatch.CopyVertexData3f(vVerts);
       
    glutPostRedisplay();
}

//根据空格次数。切换不同的“窗口名称”
void keyPressFunc(unsigned char key, int x, int y){
    
}

//检查OpenGL API是否安全可用
int checkOpenGLInit(void){
   GLenum status = glewInit();
    if(status != GLEW_OK){
        printf("GLEW Error:%s\n",glewGetErrorString(status));
        return 1;
    }
    return 0;
}


int main(int argc,char *argv[])
{
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    glutInitWindowSize(600, 600);
    //申请一个双缓存区、颜色缓存区、深度缓存区、模板缓存区
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    //创建window的名称
    glutCreateWindow("移动矩形,观察颜色");
    
    //注册回调函数(改变尺寸)
    glutReshapeFunc(changeSize);
    //点击空格时,调用的函数
    glutKeyboardFunc(keyPressFunc);
    //特殊键位函数(上下左右)
    glutSpecialFunc(specialKeys);
    //显示函数
    glutDisplayFunc(renderScene);
    //判断一下是否能初始化glew库,确保项目能正常使用OpenGL 框架
    checkOpenGLInit();
    //绘制
    setupRC();
    //runloop运行循环
    glutMainLoop();
    
    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读