• Direct3D正方体光照效果


    (1) 绘制一个正方体,不指定正方体每个顶点的颜色,通过为场景添加光照效果,使得正方体看起来像是红色的。修改材质的属性和光照的属性,记录属性变化后程序运行的结果,分析结果并给出结论。

    光照的组成

    在Direct3D的光照模型中,由光源发出的光主要有3种类型:
       环境光(AmbientLight)               ——这种类型的灯光将被其他所有表面反射且被用在照亮整个场景。
       漫反射(DiffuseReflection)          ——这种灯光按照特殊方向传播。当它照射到一个表面,它将在所有方向上均匀的反射。(与位置无关,需考虑光传播方向及物体表面朝向)
       镜面反射(SpecularReflection)       ——这种灯光按照特殊方向传播。当它照射到一个表面时,它严格地按照一个方向反射。(需考虑观察者位置,光传播方向及物体表面朝向)
    1. 头文件:d3dUtility.h
    #include <d3dx9.h>
    #include <string>
    
    #ifndef __d3dUtilityH__
    #define __d3dUtilityH__
    
    //定义命名空间
    namespace d3d
    {
    
        //绘制窗体
        bool InitD3D(
    HINSTANCE hInstance,
    // [in] Application instance. //当前应用程序实例的句柄 int width, int height, // [in] Backbuffer dimensions. //窗口宽高 bool windowed, // [in] Windowed (true)or full screen (false). //窗体类型 D3DDEVTYPE deviceType, // [in] HAL or REF //设备的类型 IDirect3DDevice9** device // 设备用接口, 每个 D3D 程序至少有一个设备
       );// [out]The created device. 


       //消息循环 int EnterMsgLoop(bool (*ptr_display)(float timeDelta)); //回调函数 //处理窗口消息的函数 LRESULT CALLBACK WndProc(HWND hwnd,UINT msg, WPARAM wParam,LPARAM lParam); //窗口句柄、消息、 消息类型wParam(键盘消息) //释放资源   template<class T> void Release(T t) { if( t ) { t->Release(); t = 0; } } //删除资源   template<class T> void Delete(T t) { if( t ) { delete t; t = 0; } } //定义颜色信息 const D3DXCOLOR WHITE( D3DCOLOR_XRGB(255, 255, 255) ); //白色 const D3DXCOLOR BLACK( D3DCOLOR_XRGB( 0, 0, 0) ); //黑色 const D3DXCOLOR YELLOW( D3DCOLOR_XRGB(255, 255, 0) ); //黄色 const D3DXCOLOR CYAN( D3DCOLOR_XRGB( 0, 255, 255) ); //青色 const D3DXCOLOR MAGENTA( D3DCOLOR_XRGB(255, 0, 255) ); //紫红色 const D3DXCOLOR RED( D3DCOLOR_XRGB(255, 0, 0) ); //红色 const D3DXCOLOR GREEN( D3DCOLOR_XRGB( 0, 255, 0) ); //绿色 const D3DXCOLOR BLUE( D3DCOLOR_XRGB( 0, 0, 255) ); //蓝色                  //D3DCOLOR_XRGB(r,g,b) - Alpha值为1,三个byte分别表示红,绿,蓝



    每种类型的光都可以使用D3DCOLORVALUE结构或D3DXCOLOR来描述光的颜色
    
    
    //类型:D3DXCOLOR
      //红色环境光
    //const D3DXCOLOR redAmbient(1.0f, 0.0f, 0.0f, 1.0f);
    ////漫反射光
    //const D3DXCOLOR blueDiffuse(0.0f, 0.0f, 1.0f, 1.0f);
    ////镜面反射光
    //const D3DXCOLOR whiteSpecular(1.0f, 1.0f, 1.0f, 1.0f);
    
    
    
    //声明材质
    D3DMATERIAL9 InitMtrl(D3DXCOLOR a /*环境光的颜色*/ , D3DXCOLOR d /*漫反射光的颜色*/, D3DXCOLOR s /*镜面光的颜色*/, D3DXCOLOR e /*增强物体的亮度*/, float p /*镜面高光点*/ );
    //定义材质颜色
    //白色材质
    const D3DMATERIAL9 WHITE_MTRL  = InitMtrl(WHITE, WHITE, WHITE, BLACK, 2.0f);
    //红色材质
    const D3DMATERIAL9 RED_MTRL    = InitMtrl(RED, RED, RED, BLACK, 2.0f);
    //绿色材质
    const D3DMATERIAL9 GREEN_MTRL  = InitMtrl(GREEN, GREEN, GREEN, BLACK, 2.0f);
    //蓝色材质
    const D3DMATERIAL9 BLUE_MTRL   = InitMtrl(BLUE, BLUE, BLUE, BLACK, 2.0f);
    //黄色材质
    const D3DMATERIAL9 YELLOW_MTRL = InitMtrl(YELLOW, YELLOW, YELLOW, BLACK, 2.0f);
    
    //d3dmaterial9
    //物体表面对光的反射百分比
    //Diffuse:指定此材质表面对漫射光的反射率
    //Ambient——指定此材质表面对环境光的反射率;
    //Specular——指定此材质表面对镜面光的反射率;
    //Emissive——增强物体的亮度。
    //Power——指定镜面高光点的锐度
    
    
    //声明光源
    //方向光(只有方向,没有位置)
    D3DLIGHT9 InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color);
    //点光源(只有位置,没有方向)
    D3DLIGHT9 InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color);
    //聚光灯(既有位置,又有方向)
    D3DLIGHT9 InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color);
    
    
    //创建法向量(应用求三角锥的法向量)
    //D3DXVECTOR3 CreatNormalVector(D3DXVECTOR3 P0,D3DXVECTOR3 P1,D3DXVECTOR3 P2){
    //    向量(以原点为起始点)
    //    
    //    D3DXVECTOR3 P3;//结果
    //
    //    向量的减法
    //    D3DXVECTOR3 U1=P1-P0; //(方向为p0->p1)
    //    D3DXVECTOR3 V1=P2-P0; //(方向为p0->p2)
    //
    //    结构体
    //    D3DXVECTOR3 *D3DXVec3Cross{
    //        D3DXVECTOR3 *out; //结果
    //        const D3DXVECTOR3 *pv1;
    //        const D3DXVECTOR3 *pv2;
    //    }
    //    向量的叉积p3 = U1 * V1 
    //    D3DXVec3Cross(&P3,&U1,&V1);

    // 法向量归一化 // 结构体 // /* // D3DXVECTOR3 *D3DXVec3Normalize( // _Inout_ const D3DXVECTOR3 *pOut, // _In_ const D3DXVECTOR3 *pV // ); // // pOut 操作的结果 // pV 操作的源 // // 输入放在第二个参数,输出放在第一个参数。 // // 操作的过程:输入三维的向量,将向量归一化后输出(也就是保证向量模为1) // 比如输入的三维向量为P3( a, b, c ),那么输出的结果为v_out(a / L, b / L, c / L) // L = sqrt( a^2 + b^2 + c^2 ) // // */ // D3DXVec3Normalize(&P3,&P3); // // return P3; // //} //D3DXVECTOR3 P0(-1,0,-1); //D3DXVECTOR3 P1(0,1,0); //D3DXVECTOR3 P2(1,0,-1); //D3DXVECTOR3 P3 = CreatNormalVector(P0,P1,P2); } #endif // __d3dUtilityH__
    2. d3dUtility.cpp
    //引入头文件
    #include "d3dUtility.h" //函数调用:初始化D3D bool d3d::InitD3D(HINSTANCE hInstance,int width, int height,bool windowed,D3DDEVTYPE deviceType,IDirect3DDevice9** device) //当前应用程序实例的句柄、 窗口宽高、 窗台类型、 设备类型、 设备用接口 { //************* 第一部分: 创建一个窗口开始 ***************
    //(1)创建程序主窗口 // Create the main application window.
    //1. 设计一个窗口类 WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; //风格样式 当窗口的水平(hredraw)或垂直(vredraw)尺寸发生变化时,窗口将被重绘 wc.lpfnWndProc = (WNDPROC)d3d::WndProc; //指定回调函数名(处理窗口产生的消息)的指针 wc.cbClsExtra = 0; //类额外内存 wc.cbWndExtra = 0; //窗口额外内存 wc.hInstance = hInstance; //当前应用程序实例的句柄,由 WinMain 传入 wc.hIcon = LoadIcon(0, IDI_APPLICATION); //图标 wc.hCursor = LoadCursor(0, IDC_ARROW); //光标 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置窗口背景色,调用函数GetStockObject设置,需要把返回值强制转换成HBRUSH类型 wc.lpszMenuName = 0; //菜单名,0 为无菜单 wc.lpszClassName = L"1704210731_绘制图形"; // 指向窗口名的指针   
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //2. 注册窗口类 //传入WNDCLASS类型的变量地址 if( !RegisterClass(&wc) ) { ::MessageBoxA(0, "注册窗口失败!", 0, 0); return false; }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //3. 注册成功后,创建窗口 HWND hwnd = 0; hwnd = ::CreateWindow( L"1704210731_绘制图形", L"1704210731_绘制图形", WS_EX_TOPMOST,0, 0, width, height,0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); //和 wc.lpszClassName 相同、窗口的显示名称、指定这个窗口是顶部式窗口、表示窗口的横|纵坐标为默认值、表示窗口的宽|高为默认值、当前应用程序实例的句柄 //窗口创建失败 if( !hwnd ) { ::MessageBoxA(0, "窗口创建失败!", 0, 0); return false; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //4. 窗口显示 //传入CreateWindow返回的HWND类型参数 ::ShowWindow(hwnd, SW_SHOW); //显示窗口,用窗口句柄hwnd来指定需要显示的窗口 //因为还没有写窗口过程的回调函数,所以只能在后台运行 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //5. 窗口更新 //传入CreateWindow返回的HWND类型参数 ::UpdateWindow(hwnd); //************* 第一部分: 创建一个窗口结束 *************** //************* 第二部分: 初始化 D3D 开始 *************** //当显示了一个窗口后,需要继续创建一个Direct3D 9设备,这个设备用于绘制3D场景。 //(2)初始化 D3D 设备 // Init D3D:   //存储设备信息 HRESULT hr = 0; //COM 要求所有的方法都会返回一个 HRESULT 类型的错误号 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Step 1: Create the IDirect3D9 object. //1. 获取IDirect3D9 接口 IDirect3D9* d3d9 = 0; //(1)创建IDirect3D9 接口,这个接口用于获得物理设备的信息和创建一个IDirect3DDevice接口 d3d9 = Direct3DCreate9(D3D_SDK_VERSION); //(1)在创建一个IDirect3D9 接口对象来显示设备时 //(3)应该先设置该设备接口对象的顶点处理类型(硬件顶点处理类型、软件顶点处理类型) //(2)在这之前需要判断显卡是否支持这个技术类型
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //创建失败 if( !d3d9 ) { ::MessageBoxA(0, "创建IDirect3D9接口失败!", 0, 0); return false; }
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Step 2: Check for hardware vp. //2. 检测显卡是否支持顶点转换和光照 //D3DCAPS9 保存了设备性能信息(包含顶点处理,纹理,shader等信息) D3DCAPS9 caps; //(2)判断显卡是否支持这个技术类型 //获取设备性能 d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps); //显卡、设备类型(HAL)通过硬件抽象层(HAL,Hardware Abstraction Layer)操作图形设备、返回一个已初始化的D3DCAPS9 结构 //硬件设备( D3DDEVTYPE_HAL ),软件设备(D3DDEVTYPE_REF)
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //将顶点运算类型用变量vp保存供以后使用 int vp = 0; //设备性能是否可以使用硬件顶点处理 if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) //硬件顶点处理 vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //软件顶点处理 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Step 3: Fill out the D3DPRESENT_PARAMETERS structure. //初始化一个D3DPRESENT_PARAMETERS结构实例,这个结构包含了许多数据成员允许我们制定将要创建的IDirect3DDevice9接口的特性。 D3DPRESENT_PARAMETERS d3dpp; d3dpp.BackBufferWidth = width; //后备缓冲宽640像素 d3dpp.BackBufferHeight = height; //后备缓冲高480像素 d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; //后备缓冲模式:32 位像素格式 d3dpp.BackBufferCount = 1; //后备缓冲表面的数量 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; //全屏抗锯齿的类型 d3dpp.MultiSampleQuality = 0; //全屏抗锯齿的质量等级 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //表面在交换链中是如何被交换的 d3dpp.hDeviceWindow = hwnd; //与设备相关的窗口句柄,在窗口绘制 d3dpp.Windowed = windowed; //窗口模式 d3dpp.EnableAutoDepthStencil = true; //自动创建深度|模版缓冲 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; //深度|模版缓冲的格式 深度值用24位二进制表示,模板8位 d3dpp.Flags = 0; //附加特性 d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; //刷新率 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //交换链中后台缓存切换到前台缓存的最大速率,立即交换 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Step 4: Create the device. //假如能支持硬件顶点处理,创建一个基于已经初始化好的D3DPRENSENT_PARAMENTS结构的IDirect3DDevice9对象 hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, // primary adapter //主显卡 deviceType, // device type //设备类型 hwnd, // window associated with device //窗口句柄 vp, // vertex processing //顶点处理方式 &d3dpp, // present parameters //指定一个已经初始化好的D3DPRESENT _PARAMETERS实例 device); // return created device //返回创建的设备
    //创建失败 if( FAILED(hr) ) { // try again using a 16-bit depth buffer //将深度|模版缓冲的格式改为16位的深度缓冲 d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //创建 hr = d3d9->CreateDevice( D3DADAPTER_DEFAULT, deviceType, hwnd, vp, &d3dpp, device); //16位的深度缓冲的对象创建失败 if( FAILED(hr) ) { d3d9->Release(); // done with d3d9 object //释放资源 ::MessageBoxA(0, "创建设备失败!", 0, 0); return false; } } d3d9->Release(); // done with d3d9 object return true; } //消息循环 int d3d::EnterMsgLoop( bool (*ptr_display)(float timeDelta) ) { MSG msg; ::ZeroMemory(&msg, sizeof(MSG)); static float lastTime = (float)timeGetTime(); while(msg.message != WM_QUIT) { if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; }



    材质:物体表面对光的反射百分比。

    //3.  (1)创建材质
    //材质球
        //d3dmaterial9 red;
        //red.diffuse  = d3dxcolor(1.0f, 0.0f, 0.0f, 1.0f); // red
        //red.ambient  = d3dxcolor(1.0f, 0.0f, 0.0f, 1.0f); // red
        //red.specular = d3dxcolor(1.0f, 0.0f, 0.0f, 1.0f); // red
        //red.emissive = d3dxcolor(0.0f, 0.0f, 0.0f, 1.0f); // no emission
        //red.power = 5.0f;
        ////指定当前材质
        ////setmaterial(const d3dmaterial9 *pmaterial)
        //device->setmaterial(&red);
    
    //结构体
    //typedef struct _D3DMATERIAL9{
    //    D3DXCOLOR Diffuse /*漫反射*/,Ambient/*环境光*/,Specular/*镜面光*/,Emissive/*增强物体的亮度*/;
    //    float Power/*镜面高光点*/;
    //}D3DMATERIAL9;

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //创建材质函数 D3DMATERIAL9 d3d::InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p) {
       //材质对象 D3DMATERIAL9 mtrl;
      //材质的颜色 mtrl.Ambient
    = a; //材质环境光的颜色 mtrl.Diffuse = d; //材质漫反射光的颜色 mtrl.Specular = s; //材质镜面光的颜色 mtrl.Emissive = e; //增强亮度的颜色 mtrl.Power = p; //光的强度 return mtrl; }
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //4. (1)创建光源
    //光源结构体
    //typedef struct _D3DLIGHT9 {
      //直射光
    //    D3DLIGHTTYPE Type; /*光源类型:点光源、方向光源、聚光灯*/
    //    //灯光类型,共3种:D3DLIGHT_POINT、D3DLIGHT_DIRECTIONAL(Directional)、D3DLIGHT_SPOT
    //
    //    //材质光的颜色
    //    D3DCOLORVALUE Diffuse;  /*光源发出的漫反射光颜色*/
    //    D3DCOLORVALUE Specular; /*镜面光的颜色*/
    //    D3DCOLORVALUE Ambient; /*环境光的颜色*/
    //
    //    D3DVECTOR Position;  //位置(点光源没有方向有位置),用向量表示的光源世界坐标位置(对方向光无效)
    //    D3DVECTOR Direction; //方向(方向光有方向没有位置没有角度),用向量表示的光源世界坐标照射方向(对点光源无效)
    //    float Range;  //角度,灯光能够传播的最大范围(对方向光无效)
    //    float Falloff; //衰弱,灯光从内圆锥到外圆锥之间的强度衰减(仅对聚光灯有效),该值通常设为1.0f。
    //
    //    //灯光衰减变量,用来定义灯光强度的传播距离衰减(对方向光无效)
    //    float Attenuation0; /*定义恒定衰减*/
    //    float Attenuation1; /*定义线性衰减*/
    //    float Attenuation2; /*定义二次衰减*/
    //    /*Attenuation0通常为 0.0f,Attenuation1通常为1.0f,Attenuation2通常为0.0f。*/
    //
    //    float Theta; /*指定灯光内圆锥的角度(仅对聚光灯有效),单位是弧度*/
    //    float Phi; /*指定外圆锥的角度(仅对聚光灯有效),单位是弧度*/
    //} D3DLIGHT9;
    
    //(3)设置光源
        //D3DLIGHT9 light;
        //::ZeroMemory(&light, sizeof(light));
        //light.Type      = D3DLIGHT_DIRECTIONAL;
        //light.Ambient   = d3d::RED;
        //light.Diffuse   = d3d::RED * 0.3f;
        //light.Specular  = d3d::RED * 0.6f;
        ////方向光:下面到上面
        //light.Direction = D3DXVECTOR3(0.0f,-1.0f,0.0f);s
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    //方向光 D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color) {      //光照对象 D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light));
         //类型:方向光 light.Type
    = D3DLIGHT_DIRECTIONAL;
         //光照的环境光的颜色 light.Ambient
    = *color * 0.6f;
         //光照的漫反射的颜色 light.Diffuse
    = *color;
         //光照的镜面光的颜色 light.Specular
    = *color * 0.6f;
         //方向光的照射方向 light.Direction
    = *direction; return light; } //点光源 D3DLIGHT9 d3d::InitPointLight(D3DXVECTOR3* position, D3DXCOLOR* color) { D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_POINT;
    light.Ambient
    = *color * 0.6f; light.Diffuse = *color; light.Specular = *color * 0.6f;
      
       //点光源的照射位置 light.Position
    = *position;
       //角度 light.Range
    = 1000.0f;
      

       //灯光衰弱变量 light.Attenuation0
    = 1.0f; light.Attenuation1 = 0.0f; light.Attenuation2 = 0.0f; return light; } //聚光灯 D3DLIGHT9 d3d::InitSpotLight(D3DXVECTOR3* position, D3DXVECTOR3* direction, D3DXCOLOR* color) { D3DLIGHT9 light; ::ZeroMemory(&light, sizeof(light));    //聚光灯 light.Type = D3DLIGHT_SPOT;
      
       //光照的反射率 light.Ambient
    = *color * 0.0f; light.Diffuse = *color; light.Specular = *color * 0.6f;
      
       //位置和方向 light.Position
    = *position; light.Direction = *direction;
        
       //传播的最大范围角度 light.Range
    = 1000.0f;
      
       //内外圆锥之间的强度衰弱 light.Falloff
    = 1.0f;
        
       //衰弱类型变量 light.Attenuation0
    = 1.0f; light.Attenuation1 = 0.0f; light.Attenuation2 = 0.0f;

       //内外圆锥角度 light.Theta
    = 0.4f; light.Phi = 0.9f; return light; }
    流程:
    1.定义带法向量的顶点结构体 2.创建顶点缓存并写数据 3.创建材质,并设置材质(设置材质对每种光的反射率) 4.创建光源,启动光源(设置光源的位置,方向和颜色) 5.设置取景变换和投影变换 6.绘制三角锥体
    3. d3dinit.cpp
    //////////////////////////////////////////////////////////////////////////////////////////////////
    
    #include "d3dUtility.h"
    
    //全局常量 const int Width = 640; const int Height = 480; // Globals //设备接口初始化 IDirect3DDevice9* Device = 0; //创建指向顶点缓冲区的指针对象 IDirect3DVertexBuffer9* cube = 0; //创建指向索引缓冲区的指针对象 //IDirect3DIndexBuffer9* IB = 0; //ID3DXMesh* sphere; // Framework Functions //定义结构体表示顶点 //创建带有颜色的顶点结构 //1. 定义带法向量的顶点结构体 struct Vertex { Vertex(){} //构造函数(初始化) Vertex(float x, float y, float z, float nx, float ny, float nz) { //顶点信息 _x = x; _y = y; _z = z; //法向量的信息 _nx = nx; _ny = ny ; _nz = nz; } //成员变量 float _x, _y, _z; //成员变量(法线) float _nx, _ny, _nz; //静态成员(顶点结构) static const DWORD FVF; }; //顶点格式 //让顶点信息包含法向量D3DFVF_NORMAL的信息 const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL; //设置 bool Setup() { //1.创建缓冲区 //创建顶点缓冲 //顶点缓存接口IDirect3DVertexBuffer9() //Device->CreateVertexBuffer(4*sizeof(ColorVertex), D3DUSAGE_WRITEONLY,ColorVertex::FVF, D3DPOOL_DEFAULT, &sanjiaozhui, 0); //顶点缓冲区的长度4个、对缓存的操作(不能对缓存区进行读取)、灵活顶点格式 、顶点缓冲区的内存类型自动调度 、顶点缓冲区指针地址IDirect3DVertexBuffer9**、保留参数 //2. 创建顶点缓存并写数据
        //
    IDirect3DVertexBuffer9* cube = 0;
      
      Device->CreateVertexBuffer(36*sizeof(Vertex), D3DUSAGE_WRITEONLY,Vertex::FVF, D3DPOOL_DEFAULT, &cube, 0);
    //D3DXCreateSphere(Device,1.0f,20,20,&sphere,0);
    
        //创建索引缓存
        //索引缓存接口CreateIndexBuffer()
        //创建索引缓存并写数据
        /*Device->CreateIndexBuffer(
            36*sizeof(WORD),
            D3DUSAGE_WRITEONLY,
            D3DFMT_INDEX16,
            D3DPOOL_DEFAULT,
            &IB,
            0);*/
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        
        //访问顶点缓存内容
        //创建指向顶点结构体的指针对象
        Vertex *vertexs;
        //锁定访问的顶点缓冲区
        cube->Lock(0, 0, (void**)&vertexs, 0);
        //(1)UINT类型OffsetToLock,偏移量
        //(2)UINT类型的SizeToLock,所要锁定的字节数
        //(3)锁定整个缓冲区,获取指向缓存内容的指针
        //(4)描述锁定的方式
    
        //(2)对顶点缓冲区进行操作,将顶点数据写入
         //前面
        //法向量朝前
        vertexs[0] =  Vertex(-1.0f,  0.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        vertexs[1] =  Vertex(-1.0f,  2.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        vertexs[2] =  Vertex( 1.0f,  2.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        vertexs[3] =  Vertex(-1.0f,  0.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        vertexs[4] =  Vertex( 1.0f,  2.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        vertexs[5] =  Vertex( 1.0f,  0.0f,  -1.0f,  0.0f,0.0f,-1.0f);
        
        //上面
        //法向量朝上
        vertexs[6] =  Vertex(-1.0f,  2.0f,  -1.0f,   0.0f,1.0f,0.0f);
        vertexs[7] =  Vertex(-1.0f,  2.0f,   1.0f,   0.0f,1.0f,0.0f);
        vertexs[8] =  Vertex( 1.0f,  2.0f,   1.0f,   0.0f,1.0f,0.0f);
        vertexs[9] =  Vertex(-1.0f,  2.0f,  -1.0f,   0.0f,1.0f,0.0f);
        vertexs[10]=  Vertex( 1.0f,  2.0f,   1.0f,   0.0f,1.0f,0.0f);
        vertexs[11]=  Vertex( 1.0f,  2.0f,  -1.0f,   0.0f,1.0f,0.0f);
    
        //右边
        //法向量朝右
        vertexs[12] =  Vertex( 1.0f,  0.0f,  -1.0f,  1.0f,0.0f,0.0f);
        vertexs[13] =  Vertex( 1.0f,  2.0f,  -1.0f,  1.0f,0.0f,0.0f);
        vertexs[14] =  Vertex( 1.0f,  2.0f,   1.0f,  1.0f,0.0f,0.0f);
        vertexs[15] =  Vertex( 1.0f,  0.0f,  -1.0f,  1.0f,0.0f,0.0f);
        vertexs[16] =  Vertex( 1.0f,  2.0f,   1.0f,  1.0f,0.0f,0.0f);
        vertexs[17] =  Vertex( 1.0f,  0.0f,   1.0f,  1.0f,0.0f,0.0f);
    
        //左边
        //法向量朝左
        vertexs[18] =  Vertex(-1.0f,  0.0f,  -1.0f,  -1.0f,0.0f,0.0f);
        vertexs[19] =  Vertex(-1.0f,  2.0f,   1.0f,  -1.0f,0.0f,0.0f);
        vertexs[20] =  Vertex(-1.0f,  2.0f,  -1.0f,  -1.0f,0.0f,0.0f);
        vertexs[21] =  Vertex(-1.0f,  0.0f,  -1.0f,  -1.0f,0.0f,0.0f);
        vertexs[22] =  Vertex(-1.0f,  0.0f,   1.0f,  -1.0f,0.0f,0.0f);
        vertexs[23] =  Vertex(-1.0f,  2.0f,   1.0f,  -1.0f,0.0f,0.0f);
    
        //后面
        //法向量朝后
        vertexs[24] =  Vertex(-1.0f,  0.0f,   1.0f, 0.0f,0.0f,1.0f);
        vertexs[25] =  Vertex( 1.0f,  2.0f,   1.0f, 0.0f,0.0f,1.0f);
        vertexs[26] =  Vertex(-1.0f,  2.0f,   1.0f, 0.0f,0.0f,1.0f);
        vertexs[27] =  Vertex(-1.0f,  0.0f,   1.0f, 0.0f,0.0f,1.0f);
        vertexs[28] =  Vertex( 1.0f,  0.0f,   1.0f, 0.0f,0.0f,1.0f);
        vertexs[29] =  Vertex( 1.0f,  2.0f,   1.0f, 0.0f,0.0f,1.0f);
    
        //下面
        //法向量朝下
        vertexs[30] =  Vertex(-1.0f,  0.0f,  -1.0f, 0.0f,-1.0f,0.0f);
        vertexs[31] =  Vertex( 1.0f,  0.0f,   1.0f, 0.0f,-1.0f,0.0f);
        vertexs[32] =  Vertex(-1.0f,  0.0f,   1.0f, 0.0f,-1.0f,0.0f);
        vertexs[33] =  Vertex(-1.0f,  0.0f,  -1.0f, 0.0f,-1.0f,0.0f);
        vertexs[34] =  Vertex( 1.0f,  0.0f,  -1.0f, 0.0f,-1.0f,0.0f);
        vertexs[35] =  Vertex( 1.0f,  0.0f,   1.0f, 0.0f,-1.0f,0.0f);
    
        
        //解锁顶点缓冲区
        cube->Unlock();
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            
        //2. (2)访问索引缓存区的内容
        //创建指向索引缓冲区指针对象
        //WORD* indices = NULL;
     //   IB->Lock(0,0,(void**)&indices,0); 
    
        ////前面
        //indices[0]  = 6; indices[1]  = 1; indices[2]  = 0;
        //indices[3]  = 0; indices[4]  = 5; indices[5]  = 6;
    
        ////后面
        //indices[6]  = 7; indices[7]  = 2; indices[8]  = 3;
        //indices[9]  = 3; indices[10] = 4; indices[11] = 7;
    
        ////上面
        //indices[12]  = 5; indices[13]  = 6; indices[14]  = 3;
        //indices[15]  = 3; indices[16]  = 4; indices[17]  = 5;
    
        ////下面
        //indices[18]  = 0; indices[19]  = 1; indices[20]  = 2;
        //indices[21]  = 2; indices[22] = 7; indices[23] = 0;
    
        ////左面
        //indices[24]  = 5; indices[25]  = 0; indices[26]  = 7;
        //indices[27]  = 7; indices[28]  = 4; indices[29]  = 5;
    
        ////右面
        //indices[30]  = 6; indices[31]  = 1; indices[32]  = 2;
        //indices[33]  = 2; indices[34] = 3; indices[35] = 6;
    
        ////解锁缓冲区
        //IB->Unlock();
    
    
        //////////////////////////////////////////////////////////////////////////
    
        //3.(1) 创建材质对象
        D3DMATERIAL9 mtrl;
        //材质为白色(封装函数)
        mtrl = d3d:: WHITE_MTRL;
    //白色材质
    const D3DMATERIAL9 WHITE_MTRL  = InitMtrl(WHITE, WHITE, WHITE, BLACK, 2.0f);
    // (2) 设置材质
        Device->SetMaterial(&mtrl);
    SetMaterial(CONST D3DMATERIAL9 *pMaterial)函数用于指定当前材质。
    //创建并设置材质
    D3DMATERIAL9 red; ::ZeroMemory(&red, sizeof(red)); red.Diffuse = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red red.Ambient = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red red.Specular = D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f); // red red.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f); // no emission red.Power = 5.0f;


     D3DMATERIAL9 mtrl;

      mtrl.Ambient = d3d::RED;

      mtrl.Diffuse = d3d::RED;

      mtrl.Specular = d3d::RED;

      mtrl.Emissive = d3d::BLACK;

      mtrl.Power = 5.0f;

      Device->SetMaterial(&mtrl);

    //红色材质
    const D3DMATERIAL9 RED_MTRL  = InitMtrl(RED, RED, RED, BLACK, 5.0f);

    //
    4. 光源
    //(1)光源对象 D3DLIGHT9 light; //(2)光源的颜色 D3DXCOLOR c = d3d::RED; //3维向量 //(3)方向从下到上 D3DXVECTOR3 direction(0.0f,1.0f,0.0f); //(4)位置 //D3DXVECTOR3 pos(0.0f,0.0f,-1.0f); //(5)方向光 light = d3d::InitDirectionalLight(&direction,&c);
    D3DLIGHT9 d3d::InitDirectionalLight(D3DXVECTOR3* direction, D3DXCOLOR* color)
    {
    
            D3DLIGHT9 light;
            ::ZeroMemory(&light, sizeof(light));
    light.Type = D3DLIGHT_DIRECTIONAL;
    light.Ambient = *color * 0.6f; light.Diffuse = *color; light.Specular = *color * 0.6f;
    light.Direction = *direction; return light; }
    //(6) 设置0号光
        Device->SetLight(0,&light);
        //(7) 开启0号光(开启光照效果)
        Device->LightEnable(0,true);
    
        //////////////////////////////////////////////////////////////////////////

    //5. 设置取景变换和投影变换、视口变换 //取景变换 D3DXVECTOR3 position(0.0f, 0.0f, -3.0f); D3DXVECTOR3 target(0.0f, 0.0f, 0.0f); D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); D3DXMATRIX V; D3DXMatrixLookAtLH(&V, &position, &target, &up); Device->SetTransform(D3DTS_VIEW, &V); //投影变换 //观察坐标系 -> 投影坐标 //创建一个投影矩阵 D3DXMATRIX proj; D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * 0.5f, float(640)/float(480),1.0f, 1000.0f); //获得的投影矩阵 、 y轴向上的视角(直角)、前裁剪面的高宽比 、最近的平面(前裁剪面距离) 、最远的平面(后裁剪面距离) Device->SetTransform(D3DTS_PROJECTION, &proj); //投影变换 //视口变换 D3DVIEWPORT9 vp={0,0,Width,Height,0,1}; //左上角为原点(0,0)、屏幕宽|高、最小|最大深度缓冲值 Device->SetViewport(&vp); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //6. 改变渲染状态 /开启规范化法向量 //使用了自定义的顶点格式中有使用法向量的需要开启 Device->SetRenderState(D3DRS_NORMALIZENORMALS, true); //开启光源 //要为每个顶点设定法线,只有设置了法线,灯光才会起作用 Device->SetRenderState(D3DRS_LIGHTING, true); //镜面光 Device->SetRenderState(D3DRS_SPECULARENABLE, false); //使用顶点颜色进行渲染,如果不禁用的话,将会看到一个黑色的多边形 //Device->SetRenderState(D3DRS_LIGHTING, FALSE); //因为使用顶点颜色渲染,所以要禁用光照处理 //线模式 //Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME); //允许渲染背面 //消隐模式,按照三角形单元的顶点绕序进行背面消隐 //关闭“挑选”功能,允许渲染背面 Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); /*Device->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_FLAT);*/ //平面着色 return true; } //释放存储空间 void Cleanup() { d3d::Release<IDirect3DVertexBuffer9*>(cube); //d3d::Release<ID3DXMesh*>(sphere); }
    //图形的渲染
    bool Display(float timeDelta) { if( Device ) // Only use Device methods if we have a valid device. { Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0); //绘制目标表面(后台缓存)|深度缓存 黑色 深度缓存值为1.0 //对表面执行清除操作 //开始绘制 Device->BeginScene(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //1.设置数据流的来源(绘制图形流水线) //指定数据流输入源,将顶点缓存和数据流进行链接 Device->SetStreamSource(0, cube, 0, sizeof(Vertex)); //数据流id、缓冲区接口即与数据流建立链接的顶点缓存的指针、从0号接口开始绑定(传播的顶点数据的起始位置)、顶点缓存中元素的大小 //2.设置索引缓存,指向索引缓存的指针 /*Device->SetIndices(IB);*/ //3.设置顶点格式:D3DFVF_XYZ Device->SetFVF(Vertex::FVF); //4. 绘制图元 Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12); //指定所要绘制的图元类型三角形列、索引增加的基数、最小索引值、顶点总数、表示索引的读取其顶点的元素索引、绘制图元的总数) //6. 旋转90度 /*D3DXMATRIX Rx; D3DXMatrixRotationX(&Rx, 3.14/2); Device->SetTransform(D3DTS_WORLD, &Rx);*/ //世界变换 D3DXMATRIX W; D3DXMatrixTranslation(&W,0.0f,-1.0f,0.0f); //Device->SetTransform(D3DTS_WORLD, &W); //旋转45度 D3DXMATRIX Rx; D3DXMatrixRotationX(&Rx,3.14/4); //Device->SetTransform(D3DTS_WORLD, &Rx); //绕Y轴连续旋转 D3DXMATRIX Ry; static float y = 0.0f; D3DXMatrixRotationY(&Ry, y); //Device->SetTransform(D3DTS_WORLD, &Ry); y+=timeDelta; //超过一圈360度 if(y >= 6.28){ y = 0.0f; }
    //实现变换 D3DXMATRIX P; P = W * Rx * Ry; Device->SetTransform(D3DTS_WORLD, &P); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //结束绘制 Device->EndScene(); // Swap the back and front buffers. Device->Present(0, 0, 0, 0); } return true; }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // WndProc //回调函数 WnProc 的函数体 //处理窗口消息的函数 LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) //创建的窗口、接受的消息、w表示word,l表示long,对于32为系统来说,分别是无符号整数(unsigned int)和长整型(long),都是32位整数。 //WndProc的第三个参数类型被定义为WORD,表示一个16位的无符号短整型,而第四个参数被定义为LONG,表示一个32的位有符号长整型,“PARAM”前缀“W”和“L”正是由此而来。 //wParam&MK_SHIFT或MK_CTRL //wParam参数指明移动或者单击鼠标键的非客户区位置 { //参数 msg 的键值判断消息的类型 switch( msg ) { // 如果是关闭窗口的消息,则用 PostQuitMessage() 来退出消息循环 case WM_DESTROY: ::PostQuitMessage(0); break; //如果按下键盘任意一个键 case WM_KEYDOWN: // 如果是 ESC 键则关闭窗口 if( wParam == VK_ESCAPE ) ::DestroyWindow(hwnd); /*if(wParam == 0x41) { D3DXVECTOR3 direction(1.0f,0.0f,0.0f); light = d3d::InitDirectionalLight(&direction, &c); } if(wParam == 0x42) { D3DXVECTOR3 position(0.0f,0.0f,-1.0f); light = d3d::InitPointLight(&position, &c); } if(wParam == 0x43) { D3DXVECTOR3 position(0.0f,0.0f,-1.0f); D3DXVECTOR3 direction(0.0f,0.0f,1.0f); light = d3d::InitSpotLight(&position, &direction,&c); }*/ break; // 如果按下鼠标左键则弹出消息框,这里 WM_LBUTTONDOWN 是鼠标左键的键值 case WM_LBUTTONDOWN: // L"Hello, World" 是消息框中显示的内容 // L"Hello" 是所在父窗口的指针 // MB_OK 表示消息框显示 “确定” 按钮 ::MessageBox(0, L"Hello, World", L"Hello", MB_OK); break; }
    return ::DefWindowProc(hwnd, msg, wParam, lParam); //用 DefWindowProc 处理一些默认的消息,比如窗口的最大化、最小化、调整尺寸等
    }
    // WinMain //程序的入口函数 int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE prevInstance, PSTR cmdLine,int showCmd) //当前实例的句柄、不使用该参数,Win32 该参数始终为 NULL、用于运行程序的命令行参数字符串、指定窗口的显示方式 { // 调用窗口初始化函数,如果调用成功则进入消息循环,否则弹出一个对话框 if(!d3d::InitD3D(hinstance,640, 480, true, D3DDEVTYPE_HAL, &Device)) //当前应用程序实例的句柄、窗口宽640、高480、窗台类型(windowed)、设备类型(HAL)、设备用接口 { ::MessageBoxA(0, "初始化失败!", 0, 0); return 0; } //顶点缓存创建失败 if(!Setup()) { ::MessageBoxA(0, "创建失败!", 0, 0); return 0; } //进入消息循环 -- 函数名调用 d3d::EnterMsgLoop( Display ); Cleanup(); Device->Release(); return 0; }

     

     

     来源:http://www.doc88.com/p-7788454774688.html

     来源:https://zhidao.baidu.com/question/686759478766334532.html

    1. 如果材质是白色,光照为红色(绿、蓝),看到的是什么颜色的锥体?
    //光照在白色的物体表面,会反射所有的光线,视觉上呈现红色(绿、蓝)
    //3. (1)材质对象
        D3DMATERIAL9 mtrl;
        //材质颜色:白色
        mtrl = d3d:: WHITE_MTRL;
        //3.  (2)设置材质
        Device->SetMaterial(& mtrl);
    //4. 光源
        //(1)光源对象
        D3DLIGHT9 light;
    
        //(2)光源的颜色:红色
        D3DXCOLOR c = d3d::RED;
    
        //3维向量
        //(3)方向从下到上
        D3DXVECTOR3 direction(0.0f,1.0f,0.0f);
        //(4)位置
        //D3DXVECTOR3 pos(0.0f,0.0f,-1.0f);
    
        //(5)方向光
        light = d3d::InitDirectionalLight(&direction,&c);
    
    
        //(6) 设置0号光
        Device->SetLight(0,&light);
        //(7) 开启0号光
        Device->LightEnable(0,true);

    2. 如果材质是红色,光照为白色呢?
    //材质本身的颜色(白色是一种包含光谱中所有颜色光的颜色)
    //光被物体吸收,经过反射(混合其他色),呈现红色。
    //3. (1)材质对象
        D3DMATERIAL9 mtrl;
        //材质为红色
        mtrl = d3d:: RED_MTRL;
        //3.  (2)设置材质
        Device->SetMaterial(& mtrl);
    
        
        //4. 光源
        //(1)光源对象
        D3DLIGHT9 light;
    
        //(2)光源的颜色:白色
        D3DXCOLOR c = d3d::WHITE;
    
        //3维向量
        //(3)方向从下到上
        D3DXVECTOR3 direction(0.0f,1.0f,0.0f);
        //(4)位置
        //D3DXVECTOR3 pos(0.0f,0.0f,-1.0f);
    
        //(5)方向光
        light = d3d::InitDirectionalLight(&direction,&c);
    
    
        //(6) 设置0号光
        Device->SetLight(0,&light);
        //(7) 开启0号光
        Device->LightEnable(0,true);

    3. 如果材质是红色,光照是蓝色(绿色)呢?
    //吸收蓝光(绿光),不反射任何颜色的光,呈现黑色。
    (材质颜色如果吸收光谱内的所有可见光,不反射任何颜色的光,人眼的感觉就是黑色的)

    4. 如果材质是红色,光照是红色呢?
    红色
    //吸收红色可见光,反射同色光,视觉上呈现红色。

    白色材质反射所有的光;同色材质反射同色的光;其他材质色吸收所有的光,不反射任何光线。
  • 相关阅读:
    15.5.3 【Task实现细节】状态机的结构
    JavaWeb-EL的11个内置对象
    JavaWeb-EL入门
    JavaWeb-BeanUtils
    JavaWeb-JavaBean
    JavaWeb-JSP动作标签
    JavaWeb-include和taglib指令
    JavaWeb-pageContext对象
    JavaWeb-page指令
    JavaWeb-URL重写
  • 原文地址:https://www.cnblogs.com/sjslove/p/12774993.html
Copyright © 2020-2023  润新知