zoukankan      html  css  js  c++  java
  • (转)从零实现3D图像引擎:(1)环境配置与项目框架

    0. 要学懂3D程序设计,必然要精通3D相关的线性代数、3D几何、复分析等相关知识,我也因为如此才开始这个博客系列的写作,不自己实现,就不是自己的东西,从今天开始,将会把所学的数学知识,从数学推导到代码实现的心得全部记录于此。最终得到一个独立的3D图像引擎,也就完成了对3D图像知识的基本学习。

    1. 文章布局。除了本文,所有文章都将由3部分组成。

    1) 数学理论推导。

    2) 不参看任何示例,只根据数学原理进行的代码实现。

    3) 项目代码下载。

    2. 语言与开发环境

    1) 语言:C/C++。

    3D游戏说白了就俩字:速度。所以对于面向对象这种东西,在速度面前完全可以无视,而且对于数学和图形库来说,本来也没有过多的对象间关系,多是数据结构与函数的关系,所以C++特性我应该不会用很多,有时为了速度还会穿插asm、SIMD和FPU的使用。

    2) 开发工具:VS2010。强大到没得说。

    3) 图形接口:D3D。(DirectX SDK June 2010,下载地址:http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3021d52b-514e-41d3-ad02-438a3ba730ba)

    “给我显存地址,我就能创造一个游戏”。这是从零实现3D图像引擎的目的,也是我认为学会3D编程的必经之路。本来我想使用DirectDraw,完全不使用D3D,而且即便是DirectDraw,也只是用它来获取显存地址,其他API全都不用。但是由于现在DirectX SDK已经都没有ddraw.h了,再使用ddraw是给自己找麻烦,所以我将使用D3D,但只使用其获得表面地址。因此我将完全抛弃硬件加速,但也反而更可以了解硬件加速到底都在做什么。PS:D3D的初始化的能力更强大,在ddraw时,我们还需要重新调整窗口大小,并且每次写入像素时,还要考虑到窗口边框所造成的像素偏移,而在D3D的初始化时都已经做好了。

    3. 约定与配置

    对于这个图形库,我们有以下几个约定:

    1) 支持Unicode

    2) 窗口程序,方便调试

    3) 屏幕色深32BPP

    4) 加载的位图均为24位位图

    5) 基于X86系统

    需要配置的就只有2个地方:

    1) 在VC++ Directories的Include和Lib中加入DirectX SDK相应目录

    2) Linker的Input加入d3d9.lib和d3dx9.lib

    4. 项目框架

    这是我们要在项目中用到的文件:

    3DConsole:我们实验的控制台

    3DLib:3D相关的函数,也包含了D3D表面的相关控制

    Math:数学库

    Diagnosis:诊断库,用于生成一些日志

    Helper:辅助函数库,比如读写文件等

    Math、Diagnosis、Helper今天没有用到,空着而已。

    3DConsole,要负责创建窗口、系统消息的循环等一般Win32程序的工作,并在其中适当的位置插入Game_Init()、Game_Main()、Game_Shutdown()方法的调用。这些一看代码便知,这里另外做了一些计时的工作,以将输出锁定到一定的帧数,并且在空闲时也不会总会去做判断而跑满CPU。计时器代码如下:

    3DConsole:我们实验的控制台

    3DLib:3D相关的函数,也包含了D3D表面的相关控制

    Math:数学库

    Diagnosis:诊断库,用于生成一些日志

    Helper:辅助函数库,比如读写文件等

    Math、Diagnosis、Helper今天没有用到,空着而已。

    3DConsole,要负责创建窗口、系统消息的循环等一般Win32程序的工作,并在其中适当的位置插入Game_Init()、Game_Main()、Game_Shutdown()方法的调用。这些一看代码便知,这里另外做了一些计时的工作,以将输出锁定到一定的帧数,并且在空闲时也不会总会去做判断而跑满CPU。计时器代码如下:

    // 函数定义
    DWORD GetClock()
    {
    	return GetTickCount(); 
    }
    
    void StartClock()
    {
    	g_Clock = GetClock();
    }
    
    void WaitClock()
    {
    	while((GetClock() - g_Clock) < WAIT_TIME)
    	{
    		Sleep(5);
    	}
    }

    3DLib,本文实现了对D3D的初始化,并实现了绘制一个像素的代码,代码中有注释:

    #include "CPPYIN.3DLib.h"
    
    bool _CPPYIN_3DLib::Init3DLib(HINSTANCE hInstance, HWND hWnd, int width, int height)
    {
    	IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
    
    	D3DPRESENT_PARAMETERS d3dpp;
    	d3dpp.BackBufferWidth            = width;
    	d3dpp.BackBufferHeight           = height;
    	d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
    	d3dpp.BackBufferCount            = 1;
    	d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
    	d3dpp.MultiSampleQuality         = 0;
    	d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD;
    	d3dpp.hDeviceWindow              = hWnd;
    	d3dpp.Windowed                   = TRUE;
    	d3dpp.EnableAutoDepthStencil     = true;
    	d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
    	d3dpp.Flags                      = 0;
    	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
    	d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
    
    	d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
    	d3d9->Release();
    
    	pDevice->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, 0);
    	
    	return true;
    }
    
    int _CPPYIN_3DLib::DrawPixel(int x,int y, DWORD color)
    {
    	// 创建并初始化锁定区域
    	D3DLOCKED_RECT lr;
    	memset(&lr, 0, sizeof(lr));
    
    	// 锁定
    	pSurface->LockRect(&lr,NULL,D3DLOCK_DISCARD);
    
    	// 像素着色
    	DWORD* pBits = (DWORD*)lr.pBits;
    	pBits[x + y * (lr.Pitch >> 2)] = color;
    
    	// 解锁
    	pSurface->UnlockRect();
    
    	return 1;
    }
    
    void _CPPYIN_3DLib::FlipSurface()
    {
    	// 获取后台缓存
    	IDirect3DSurface9* backBuffer = 0;
    	pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
    
    	// 使用自定义表面填充后台缓存
    	pDevice->StretchRect(pSurface, 0, backBuffer, 0, D3DTEXF_NONE);
    
    	// GetBackBuffer所得的缓存需要被释放,否则会内存泄露
    	backBuffer->Release();
    
    	// 将交换链中的后台缓存显示
    	pDevice->Present(0, 0, 0, 0);
    }
    
    void _CPPYIN_3DLib::Release3DLib()
    {
    	pSurface->Release();
    	pDevice->Release();
    }

    最后放上框架项目源码下载:>>点击进入下载页<<

     

    转自:http://blog.csdn.net/cppyin/archive/2011/02/01/6171801.aspx

  • 相关阅读:
    preg_match()
    Ubuntu解压缩zip,tar,tar.gz,tar.bz2文件命令
    Couchbase集群
    画图工具
    谷歌打不开
    筛选重复数据的方法
    div垂直居中的N种方法 单行/多行文字(未知高度/固定高度)
    ie6 ol 序列号 bug
    IE6、7下li元素的子元素为dl,ul,ol时产生的bug
    ie6 line-height bug解决办法
  • 原文地址:https://www.cnblogs.com/CoolJie/p/1970142.html
Copyright © 2011-2022 走看看