渲染世界的Opengl<5>基础渲染代码分析

1.混合知识
OpenGL渲染的时候会把颜色值放在颜色缓冲区当中。每个片段的深度值放在深度缓冲区中
打开了OpenGL的混合功能方法:

glEnable(GL_BLEND);

打开混合功能,新的颜色会与已经存在的颜色值在颜色缓冲区中进行组合。这些颜色的组合方式不同会导致很多不同的特殊效果。

(1)组合颜色术语
目标颜色:已经存储在颜色缓冲区中的颜色。这个颜色包含单独的红绿蓝以及一个可选的alpha值。
源颜色:作为当前渲染命令的结果进入颜色缓冲区。可能与目标颜色进行交互。也可以不与之进行交互。源颜色可以包含三种或者四种颜色成分。
混合方式启用的时候,默认情况下混合方程式:

Cf=(Cs*S)+(Cd*D)

Cf:最终产生的颜色,Cs是源颜色,Cd是目标颜色。
S、D为混合因子,并且都是枚举值。
调用下面的函数对其进行设置:

glBlendFunc(GLenum S, GLenum D);

(2)改变混合方程式
其中有五个混合方程式进行选择。

GL_FUNC_ADD:Cf=(Cs*S)+(Cd*D)
GL_FUNC_SUBTRACT:Cf=(Cs*S)-(Cd*D)
GL_FUNC_REVERSE_SUBTRACT:Cf=(Cd*D)-(Cs*S)
GL_MIN:MIN(Cs,Cd)
GL_MAX:MAX(Cs,Cd)

选择函数为:

void glBlendEquation(GLenum mode);
//使用上述枚举值对混合方程式进行选择。

void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);

注意glBlendFuncSeparate函数则允许为RGB和alpha成分单独指定混合函数。

void glBlendColor(GLclampf red,GLclampf green, GLclampf blue, GLclampf alpha);

这个函数可以对常量混合函数颜色进行修改。

(3)抗锯齿
在绝大多数情况,一个独立的渲染片段会映射到计算机屏幕上的一个像素。这些像素是正方形,通常可以相当清楚地看到两种颜色的分界,他们常常被称为锯齿,会吸引眼睛的注意力,让人觉得图像非常不自然。
解决方法:OpenGL使用混合功能来混合片段的颜色,也就是把像素的目标颜色和周围的颜色进行混合。

步骤:

//首先开启抗锯齿功能,首先必须启动混合功能
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

//并且把默认的混合方程式设置为GL_ADD。
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
//使用GL_POLYGON_SMOOTH的时候,需要很多其他规则:重叠的几何图形需要不同的混合模式、并可能对场景从前向后进行排序。

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
//对其渲染模式进行微调。并且根据需要选择GL_NICEST或者GL_FASTEST。

(4)多重采样
抗锯齿处理最大优点之一是能够使得多边形边缘能够更加平滑,使渲染效果显得更加自然和逼真。然而多边形的平滑处理并不方便。抗锯齿处理是基于混合操作的。
多重采样可以解决这个问题。所有图元在每个像素上都进行多次采样,结果就存储在这个缓冲区中,每次当这个像素进行更新的时候,这些采样值进行解析,以产生一个单独的值。
如下请求一个多重采样:

//请求一个帧缓冲区作为多重采样的缓冲区。
glutDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_MULTISAMPLE);
//打开或者关闭多重采样
glEnable(GL_MULTISAMPLE);
glDisable(GL_MULTISAMPLE);

注意:关于多重采样,当它被启用的时候,点、线、多边形平滑特性都将被忽略。二者不可兼得。一种策略是:绘制直线的时候,可以考虑关闭多重采样,绘制其他实心几何图形时再打开多重采样。
注意:状态排序:上面的一种策略,导致的状态改变可能会对渲染的性能造成影响,这样需要相同状态的几何图形就可以在一起绘制。这种状态排序是在游戏中常用的提高速度的方法之一。

多重采样缓冲区在默认情况下使用片段的RGB值,并不包括颜色的alpha成分。我们可以通过glEnable来修改这些行为。
GL_SAMPLE_ALPHA_TO_COVERAGE:使用alpha值。
GL_SAMPLE_ALPHA_TO_ON:将alpha值设置为1,并且使用它。
GL_SAMPLE_COVERAGE:使用glSampleCoverage。
当启用GL_SAMPLE_COVERAGE时,glSampleConverage函数允许指定一个特定的值,他是与片段覆盖值进行按位与操作的结果。

void glSampleCoverage(GLclampf value, GLclampf invert);
  1. 基础渲染代码分析

下面列出本章节所涉及到的代码分析
(1)环带渲染模式示例代码分析

#pragma comment(lib,"GLTools.lib")
#include <GLTools.h>    // OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <math.h>
#include <GL/glut.h>



GLFrame             viewFrame;
GLFrustum           viewFrustum;
GLTriangleBatch     torusBatch;
GLMatrixStack       modelViewMatix;
GLMatrixStack       projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager     shaderManager;

//面剔除选项,以及深度测试选项
int iCull = 0;
int iDepth = 0;

//右键可以打开相应的菜单对其渲染模式进行选择。
//注意main函数当中的glutCreateMenu回调函数
//就是调用这个函数创建相应的菜单。
//注意这个函数的格式。
//value值为菜单条目的索引值。
void ProcessMenu(int value)
{
    switch (value)
    {
    case 1:
        //打开或者关闭深度测试
        iDepth = !iDepth;
        break;

    case 2:
        //打开或者关闭背面剔除
        iCull = !iCull;
        break;

    case 3:
        //设置,正面反面,全部面渲染。
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        break;

    case 4:
        //设置正面反面,全部线框渲染。
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        break;

    case 5:
        //设置正面背面全部点渲染
        glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
        break;
    }

    glutPostRedisplay();
}


//实际绘制函数
void RenderScene(void)
{
    // 清除屏幕和缓冲区当中数据
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 决定是否开启相关的功能。
    //是否开启表面剔除
    if (iCull)
        glEnable(GL_CULL_FACE);
    else
        glDisable(GL_CULL_FACE);

    // 是否开启深度测试
    if (iDepth)
        glEnable(GL_DEPTH_TEST);
    else
        glDisable(GL_DEPTH_TEST);

    //向矩阵堆栈中压栈
    modelViewMatix.PushMatrix(viewFrame);
    //红色
    GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
    //shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vRed);
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, 
        transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), 
        vRed);

    //绘制相应的批次序列
    torusBatch.Draw();
    //弹栈
    modelViewMatix.PopMatrix();

    //手动刷新
    glutSwapBuffers();
}

// 渲染的基础环境设置
void SetupRC()
{
    // 背景色设置
    glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
    //初始化渲染器<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值