win32多线程编程:Win32 OpenGL编程(12) 混合及半透明效果

  混合力量是很强大就如巴尔扎克所言而图形处理中很多有趣且实用效果在OpenGL中其实都可以用混合来实现比如最最常用半透明效果这种效果在compiz3D桌面效果中得到了极致发挥让人印象深刻即使你从来不使用Linux你也可以去看看很多人秀自己Linux桌面效果视频要知道这效果出来时候连Vista都还不知道在哪呵呵可惜个桌面系统好不好不仅仅是靠谁更炫来比较

  概念

  在OpenGL中混合是指啥?就如混合般意义混合在OpenGL中指是两个图形组合只不过这个组合方式可以以很多种方式定义罢了混合是属于那种概念较为简单相关接口不算太多但是可定制内容较多所以参数复杂而且利用各个参数含义简单但是要知道在什么时候使用什么样参数却不简单那类概念和光照同类

  现实生活中最常见例子就是透过玻璃看个东西了你看到图像实际是玻璃反射光和玻璃后物体反射光穿过玻璃后在眼睛中起形成图像在OpenGL中被描述成玻璃后物体反射光和玻璃反射光混合后产生图像

  alpha这个以前我们直没有使用值在混合中发挥着关键作用般我们将其称作透明度但是事实上在混合时此值可以作为更多用途当然仅仅作为透明度使用也完全没有问题

  出于对思维导图兴趣还是来个图:



  图片看不清楚?请点击这里查看原图(大图)

  使用

  在OpenGL中将新片段成为源将已经存在图形成为目标使用时先通过 glBlendFunc{Separate}指定如何计算源和目标混合因子然后通过glBlendEquation{Separate}指定如何混合(即指定混合模式)使用步骤相当简单除了按照惯例需要用glEnable(GL_BLEND)启用外也就这两步第 2步还是在OpenGL 1.2中才加入原来只能为加模式现在在我们忽略第 2步时默认使用加模式其中附加Separate表示分别指定RGB和alpha值

  OpenGL Programming Guide:

    glBlendFunc — specy pixel arithmetic
    C Specication
    void glBlendFunc(    GLenum      sfactor,
         GLenum      dfactor);
    Parameters
    sfactor
                            Species how the red, green, blue,
                            and alpha source blending factors are computed.
                            The following symbolic constants are accepted:
                            GL_ZERO,
                            GL_ONE,
                            GL_SRC_COLOR,
                            GL_ONE_MINUS_SRC_COLOR,
                            GL_DST_COLOR,
                            GL_ONE_MINUS_DST_COLOR,
                            GL_SRC_ALPHA,
                            GL_ONE_MINUS_SRC_ALPHA,
                            GL_DST_ALPHA,
                            GL_ONE_MINUS_DST_ALPHA,
                            GL_CONSTANT_COLOR,
                            GL_ONE_MINUS_CONSTANT_COLOR,
                            GL_CONSTANT_ALPHA,
                            GL_ONE_MINUS_CONSTANT_ALPHA, and
                            GL_SRC_ALPHA_SATURATE.
                            The initial value is GL_ONE.
    dfactor
                            Species how the red, green, blue,
                            and alpha destination blending factors are computed.
                            The following symbolic constants are accepted:
                            GL_ZERO,
                            GL_ONE,
                            GL_SRC_COLOR,
                            GL_ONE_MINUS_SRC_COLOR,
                            GL_DST_COLOR,
                            GL_ONE_MINUS_DST_COLOR,
                            GL_SRC_ALPHA,
                            GL_ONE_MINUS_SRC_ALPHA,
                            GL_DST_ALPHA,
                            GL_ONE_MINUS_DST_ALPHA.
                            GL_CONSTANT_COLOR,
                            GL_ONE_MINUS_CONSTANT_COLOR,
                            GL_CONSTANT_ALPHA, and
                            GL_ONE_MINUS_CONSTANT_ALPHA.
                            The initial value is GL_ZERO.
    glBlendEquation — specy the equation used for both the RGB blend equation and the Alpha blend equation
    C Specication
    void glBlendEquation(    GLenum mode);
    Parameters
    mode
                            species how source and destination colors are combined.
                            It must be GL_FUNC_ADD, GL_FUNC_SUBTRACT,
                            GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX.


  简单使用真是非常简单(虽然参数组合可以很多)事实上见下例仅仅那么几行代码就实现了个半透明效果

//OpenGL化开始
void SceneInit( w, h)
{
    GLenum err = glewInit;
    (err != GLEW_OK)
    {
        MessageBox(NULL, _T("Error"), _T("Glew init failed."), MB_OK);
        exit(-1);
    }
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);
}
void DrawSmoothColorPyramid(GLfloat adSize)
{
     GLfloat fPyramidDatas = {    0.0, 1.0, 0.0,    //  3角锥上顶点
        -1.0, 0.0, 1.0,    // 底面左前顶点
        1.0, 0.0, 1.0,    // 底面右前下顶点
        0.0, 0.0, -1.0}; // 底面后下顶点
    GLfloat fPyramidSizeDatas[(fPyramidDatas)/(GLfloat)] = {0};
    // 计算大小
    for(  i = 0; i < 12; i)
    {
        fPyramidSizeDatas[i] = fPyramidDatas[i] * adSize;
    }
     GLfloat fPyramidColors = { 0.0, 0.0, 0.0, 0.7,
        1.0, 0.0, 0.0, 0.7,
        0.0, 1.0, 0.0, 0.7,
        0.0, 0.0, 1.0, 0.7};
     GLu ubyIndices = {    0, 1, 2,    // 正面
        0, 3, 1,    // 左侧面
        0, 2, 3,    // 右侧面
        1, 3, 2};    // 底面
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPoer(3, GL_FLOAT, 0, fPyramidSizeDatas);
    glColorPoer(4, GL_FLOAT, 0, fPyramidColors);
    for( i = 0; i < 4; i)
    {
        glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, ubyIndices+i*3);
    }
}
//这里进行所有绘图工作
void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1.0, 0.0, 0.0);

    glPushMatrix;
    DrawSmoothColorPyramid(0.5);
    DrawSmoothColorPyramid(1);
    glPopMatrix;
    glLoadIdentity;
    gluLookAt(gViewPosX, gViewPosY, gViewPosZ, gViewDirX, gViewDirY, gViewDirZ, gViewUpDirX, gViewUpDirY, gViewUpDirZ);
    glFlush;
}  


  此例是从原来2009-10-25\glCullFace改过来基本思路是在个小 3角锥外再画个大 3角锥即如下几句:

glPushMatrix;
DrawSmoothColorPyramid(0.5);
DrawSmoothColorPyramid(1);
glPopMatrix;


  除此外新添关键代码就是

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);


  两句了分别是开启混合并将混合因子设为源混合因子使用RGB+alpha值目标混合因子颜色即原颜色并且我们使用了默认混合加模式很简单吧?就两句代码而已

  另外特别注意此时我在颜色中添加进了alpha参数(原来没有)

 GLfloat fPyramidColors = { 0.0, 0.0, 0.0, 0.7,
    1.0, 0.0, 0.0, 0.7,
    0.0, 1.0, 0.0, 0.7,
    0.0, 0.0, 1.0, 0.7};


  此时表示 3角锥颜色alpha值为0.7.

  我们看看实现半透明效果是如何样





  先看左边截图根本看不到小 3角锥原因很明显外面 3角锥后绘制将其内部先绘制小 3角锥完全覆盖掉了但是右边截图我们清晰看到了内部小 3角锥呵呵我们启用了半透明效果(用混合实现)嘛



  自从决定以概念讲解和演示为主后本系列文章就像原来那样常常力图展示所有参数概念和效果了此处对混合使用可以说是最最简单我甚至都没有去glBlendEquation{Separate}但是实际使用可以相当复杂各个参数作用大家就去参考OpenGL Programming Guide



Tags:  win32多线程编程

延伸阅读

最新评论

发表评论