博客
关于我
NeHe OpenGL教程 第四十四课:3D光晕
阅读量:791 次
发布时间: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/

    你可能感兴趣的文章
    navicat连接远程mysql数据库
    查看>>
    Navicat通过存储过程批量插入mysql数据
    查看>>
    Navicat(数据库可视化操作软件)安装、配置、测试
    查看>>
    navigationController
    查看>>
    NB-IOT使用LWM2M移动onenet基础通信套件对接之APN设置
    查看>>
    NBear简介与使用图解
    查看>>
    Vue过滤器_使用过滤器进行数据格式化操作---vue工作笔记0015
    查看>>
    Ncast盈可视 高清智能录播系统 IPSetup.php信息泄露+RCE漏洞复现(CVE-2024-0305)
    查看>>
    NCNN中的模型量化解决方案:源码阅读和原理解析
    查看>>
    NCNN源码学习(1):Mat详解
    查看>>
    nc命令详解
    查看>>
    NC综合漏洞利用工具
    查看>>
    ndarray 比 recarray 访问快吗?
    查看>>
    ndk-cmake
    查看>>
    NdkBootPicker 使用与安装指南
    查看>>
    ndk特定版本下载
    查看>>
    NDK编译错误expected specifier-qualifier-list before...
    查看>>
    Neat Stuff to Do in List Controls Using Custom Draw
    查看>>
    Necurs僵尸网络攻击美国金融机构 利用Trickbot银行木马窃取账户信息和欺诈
    查看>>
    Needle in a haystack: efficient storage of billions of photos 【转】
    查看>>