博客
关于我
NeHe OpenGL教程 第四十四课:3D光晕
阅读量:789 次
发布时间:2023-02-14

本文共 2759 字,大约阅读时间需要 9 分钟。

NeHe OpenGL教程第四十四课:3D光晕

3D光晕效果实现

当镜头对准光源时,我们会观察到强烈的光晕效果。通过简单的数学计算和纹理贴图,可以很好地模拟这种效果。本文将介绍如何在OpenGL程序中实现这一效果。

实现思路

为了实现光晕效果,我们需要以下几个关键步骤:

  • 获取视景体数据:首先,我们需要了解当前视点的位置和方向。这可以通过计算视图矩阵和投影矩阵来实现。
  • 光源检测:检测光源是否在视点的可见范围内。这可以通过点是否在视景体内来判断。
  • 光晕渲染:当光源可见时,我们需要绘制光晕效果。这通常涉及到多个纹理贴图的拼接,模拟光线的扩散和折射效果。
  • 下面,我们将详细介绍光源检测和光晕渲染的实现方法。


    光源检测

    为了判断光源是否在视点的可见范围内,我们需要以下函数:

  • 获取视景体的平面方程:通过计算投影矩阵和模型视图矩阵的乘积,得到剪切矩阵。剪切矩阵可以用来确定点是否在视景体内。
  • 点是否在视景体内:通过将点坐标代入剪切矩阵方程,判断点是否满足视景体的条件。
  • 以下是光源检测的关键代码片段:

    BOOL glCamera::PointInFrustum(glPoint p) {    int i;    for(i = 0; i < 6; i++) {        if(m_Frustum[i][0] * p.x + m_Frustum[i][1] * p.y +            m_Frustum[i][2] * p.z + m_Frustum[i][3] <= 0) {            return FALSE;        }    }    return TRUE;}

    光晕渲染

    当光源可见时,我们需要绘制光晕效果。光晕的绘制通常包括以下步骤:

  • 计算光源到摄像头的距离:通过光源位置和视点位置的向量,计算光源与视点之间的距离。
  • 确定光晕的绘制位置:根据光源到视点的距离,计算光晕的绘制位置。通常,我们会绘制多个光晕,模拟光线的扩散效果。
  • 使用纹理贴图:通过不同的纹理贴图(如Halo、Glow、BigGlow、Streaks等),绘制多种光晕效果。
  • 以下是光晕渲染的关键代码片段:

    void glCamera::RenderLensFlare() {    GLfloat Length = 0.0f;    if(SphereInFrustum(m_LightSourcePos, 1.0f) == TRUE) {        // 计算光源到摄像头的距离        vLightSourceToCamera = m_Position - m_LightSourcePos;        Length = vLightSourceToCamera.Magnitude();        // 绘制光晕        RenderBigGlow(0.60f, 0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f);        RenderStreaks(0.60f, 0.60f, 0.8f, 1.0f, m_LightSourcePos, 16.0f);        RenderGlow(0.8f, 0.8f, 1.0f, 0.5f, m_LightSourcePos, 3.5f);        // ... 其他光晕绘制函数 ...    }    glDisable(GL_BLEND);    glEnable(GL_DEPTH_TEST);    glDisable(GL_TEXTURE_2D);}

    纹理贴图的使用

    为了实现光晕效果,我们需要以下四种纹理贴图:

  • Halo形光晕:用于模拟光线的圆形扩散效果。
  • Glow形光晕:用于模拟光线的流动效果。
  • BigGlow形光晕:用于模拟光线的扩散效果。
  • Streaks形光晕:用于模拟光线的折射效果。
  • 以下是绘制Halo形光晕的关键代码片段:

    void glCamera::RenderHalo(GLfloat r, GLfloat g, GLfloat b, GLfloat a, glPoint p, GLfloat scale) {    glPoint q[4];    q[0].x = (p.x - scale);    q[0].y = (p.y - scale);    q[1].x = (p.x - scale);    q[1].y = (p.y + scale);    q[2].x = (p.x + scale);    q[2].y = (p.y - scale);    q[3].x = (p.x + scale);    q[3].y = (p.y + scale);    glPushMatrix();    glTranslatef(p.x, p.y, p.z);    glRotatef(-m_HeadingDegrees, 0.0f, 1.0f, 0.0f);    glRotatef(-m_PitchDegrees, 1.0f, 0.0f, 0.0f);    glBindTexture(GL_TEXTURE_2D, m_HaloTexture);    glColor4f(r, g, b, a);    glBegin(GL_TRIANGLE_STRIP);    glTexCoord2f(0.0f, 0.0f);    glVertex2f(q[0].x, q[0].y);    glTexCoord2f(0.0f, 1.0f);    glVertex2f(q[1].x, q[1].y);    glTexCoord2f(1.0f, 0.0f);    glVertex2f(q[2].x, q[2].y);    glTexCoord2f(1.0f, 1.0f);    glVertex2f(q[3].x, q[3].y);    glEnd();    glPopMatrix();}

    整体实现流程

  • 初始化:在程序开始时,初始化光源的位置和方向。
  • 更新视景体:通过计算投影矩阵和模型视图矩阵,更新视景体的平面方程。
  • 光源检测:判断光源是否在视点的可见范围内。
  • 光晕渲染:如果光源可见,绘制光晕效果。通过多个纹理贴图,模拟光线的扩散和折射效果。
  • 渲染完成:绘制完成后,恢复默认的GL状态。

  • 通过以上方法,我们可以在OpenGL程序中实现逼真的3D光晕效果。光晕的实现主要依赖于视图矩阵、投影矩阵和纹理贴图的结合。通过合理设计和优化光晕绘制函数,可以实现多种不同风格的光晕效果,丰富3D场景的视觉效果。

    转载地址:http://ffcfk.baihongyu.com/

    你可能感兴趣的文章
    MySQL高级-MySQL锁
    查看>>
    MySQL高级-SQL优化
    查看>>
    MySQL高级-SQL优化步骤
    查看>>
    MySQL高级-内存管理及优化
    查看>>
    MySQL高级-存储过程和函数
    查看>>
    MySQL高级-索引
    查看>>
    MySQL高级-索引的使用及优化
    查看>>
    MySQL高级-视图
    查看>>
    MySQL高级-触发器
    查看>>
    Mysql高级——锁
    查看>>
    mysql高级查询~分页查询
    查看>>
    mysql高级查询之多条件的过滤查询
    查看>>
    MySQL高级配置
    查看>>
    MySQL高频面试题
    查看>>
    MySQL高频面试题的灵魂拷问
    查看>>
    MySQL(1)的使用 | SQL
    查看>>
    MySQL(2)DDL详解
    查看>>
    MySQL(3)DML详解
    查看>>
    MySQL(4)运算符 | 关联查询详解
    查看>>
    MySQL(5)条件查询 | 单行函数 | 事务详解
    查看>>