zoukankan      html  css  js  c++  java
  • 17. 增加对硬件光照的支持

    该游戏项目一开始先创建名为light.h、material.h的两个文件。

    light.h头文件用于创建灯源结构,该结构用于创建Direct3D中的灯源对象。以某种方式实现该结构,这样也可将其用于OpenGL或其他渲染系统。光源结构模仿了Direct3D中的D3DLIGHT结构,所以它们是完全兼容的。

    light.h

    #ifndef _UGP_LIGHT_H_
    #define _UGP_LIGHT_H_

    struct stLight
    {
    stLight()
    {
    type
    = 0;
    posX
    = 0, posY = 0, posZ = 0;
    dirX
    = 0, dirY = 0, dirZ = 0;
    ambientR
    = ambientG = ambientB = ambientA = 1;
    diffuseR
    = diffuseG = diffuseB = diffuseA = 1;
    specularR
    = specularG = specularB = specularA = 0;
    range
    = 0;
    falloff
    = 0;
    attenuation0
    = 0;
    attenuation1
    = 0;
    attenuation2
    = 0;
    theta
    = 0;
    phi
    = 0;
    }

    int type;
    float posX, posY, posZ;
    float dirX, dirY, dirZ;
    float ambientR, ambientG, ambientB, ambientA;
    float diffuseR, diffuseG, diffuseB, diffuseA;
    float specularR, specularG, specularB, specularA;
    float range;
    float falloff;
    float attenuation0;
    float attenuation1;
    float attenuation2;
    float theta;
    float phi;
    };

    #endif

      material.h

    // ========================================================================
    //§ material.h 文件
    //§
    //§ 【描述】:定义材质结构:stMaterial
    //§
    // ========================================================================

    #ifndef _UGP_MATERIAL_H_
    #define _UGP_MATERIAL_H_

    struct stMaterial
    {
    stMaterial()
    {
    emissiveR
    = emissiveG = emissiveB = emissiveA = 0;
    ambientR
    = ambientG = ambientB = ambientA = 1;
    diffuseR
    = diffuseG = diffuseB = diffuseA = 1;
    specularR
    = specularG = specularB = specularA = 0;
    power
    = 0;
    }

    float emissiveR, emissiveG, emissiveB, emissiveA;
    float ambientR, ambientG, ambientB, ambientA;
    float diffuseR, diffuseG, diffuseB, diffuseA;
    float specularR, specularG, specularB, specularA;
    float power;
    };

    #endif

      

        Direct3D渲染系统需要一种创建光源和材质的方法。这可以通过为渲染系统添加三个新函数来实现。第一个函数是SetMaterial(),它的参数包括材质(stMaterial)对象,并将其施加到渲染设备上。第二个新函数是SetLight(),它的参数包括灯源对象、灯源索引(因为Direct3D和OpenGL由多达8个的硬件光源,所以索引值可以是0~7),并且调用必须的Direct3D函数用于在硬件中创建和注册光源。最后一个新函数是DisalbeLight(),它以想要关闭灯源的索引为参数。给出了新增加的CD3DRenderer和CRenderInterface类。

    class CRenderInterface
    {
    // ...The beginning of the class functions...

    // 设置材质
    virtual void SetMaterial(stMaterial *mat) = 0;

    // 设置并启用光源
    virtual void SetLight(stLight *light, int index) = 0;

    // 关闭光源
    virtual void DisableLight(int index) = 0;

    // ...The rest of the class's functions...
    };


    class CD3DRenderer : public CRenderInterface
    {
    // ...The beginning of the class functions...

    // 设置材质
    void SetMaterial(stMaterial *mat);

    // 设置并启用光源
    void SetLight(stLight *light, int index);

    // 关闭光源
    void DisableLight(int index);

    // ...The rest of the class's functions...
    };

      D3DRenderer.cpp源文件实现了三个和Direct3D打交道的函数。SetMaterial()函数使用材质结构中的信息创建Direct3D材质对象,并调用Direct3D设备函数SetMaterial()将该对象直接发送给Direct3D。这同样使用于SetLight()函数。SetLight()函数的参数包括光源结构,该函数使用该参数设置D3DLIGHT9对象,并将其直接发送给Direct3D。DisableLight()函数的参数包括光源索引,它将关闭注册在该索引上的所有光源。给出了这些函数的源代码。

    // 设置材质
    void CD3DRenderer::SetMaterial(stMaterial *mat)
    {
    if(!mat || !m_Device) return;

    D3DMATERIAL9 m
    = { mat->diffuseR, mat->diffuseG,
    mat
    ->diffuseB, mat->diffuseA,
    mat
    ->ambientR, mat->ambientG,
    mat
    ->ambientB, mat->ambientA,
    mat
    ->specularR, mat->specularG,
    mat
    ->specularB, mat->specularA,
    mat
    ->emissiveR, mat->emissiveG,
    mat
    ->emissiveB, mat->emissiveA,
    mat
    ->power
    };

    m_Device
    ->SetMaterial(&m);
    }



    // 设置并启用光源
    void CD3DRenderer::SetLight(stLight *light, int index)
    {
    if(!light || !m_Device || index < 0) return;

    D3DLIGHT9 l;

    l.Ambient.a
    = light->ambientA;
    l.Ambient.r
    = light->ambientR;
    l.Ambient.g
    = light->ambientG;
    l.Ambient.b
    = light->ambientB;
    l.Attenuation0
    = light->attenuation0;
    l.Attenuation1
    = light->attenuation1;
    l.Attenuation2
    = light->attenuation2;
    l.Diffuse.a
    = light->diffuseA;
    l.Diffuse.r
    = light->diffuseR;
    l.Diffuse.g
    = light->diffuseG;
    l.Diffuse.b
    = light->diffuseB;
    l.Direction.x
    = light->dirX;
    l.Direction.y
    = light->dirY;
    l.Direction.z
    = light->dirZ;
    l.Falloff
    = light->falloff;
    l.Phi
    = light->phi;
    l.Position.x
    = light->posX;
    l.Position.y
    = light->posY;
    l.Position.z
    = light->posZ;
    l.Range
    = light->range;
    l.Specular.a
    = light->specularA;
    l.Specular.r
    = light->specularR;
    l.Specular.g
    = light->specularG;
    l.Specular.b
    = light->specularB;
    l.Theta
    = light->theta;


    if(light->type == LIGHT_POINT) l.Type = D3DLIGHT_POINT;
    else if (light->type == LIGHT_SPOT) l.Type = D3DLIGHT_SPOT;
    else l.Type = D3DLIGHT_DIRECTIONAL;

    m_Device
    ->SetLight(index, &l);
    m_Device
    ->LightEnable(index, TRUE);
    }


    // 关闭光源
    void CD3DRenderer::DisableLight(int index)
    {
    if(!m_Device) return;

    m_Device
    ->LightEnable(index, FALSE);
    }

      

    还需要在“defines.h”头文件里加入这几行代码:

    // Light type defines. 
    // 光源类型
    #define LIGHT_POINT 1      // 点光源
    #define LIGHT_DIRECTIONAL 2  // 方向光
    #define LIGHT_SPOT 3      // 聚光灯

      


  • 相关阅读:
    VS编译cmake工程提示 “无法识别的标记”错误解决方法
    Markdown
    latex公式
    ros:time::now()详解
    c++中PROTOBUF遍历所有属性及值
    ORB-SLAM3相关博文
    WSL2安装及GUI图形界面配置踩坑指南
    ROS与PCL数据转换
    手眼标定中AX=XB求解方法及MATLAB、C++代码
    正则表达式用于数据清洗
  • 原文地址:https://www.cnblogs.com/kex1n/p/2148687.html
Copyright © 2011-2022 走看看