当前位置: 首页 > news >正文

从零实现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。计时器代码如下:

// 函数定义 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(); }

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

相关文章:

  • Akka in action (第一章 介绍Akka)
  • Muduo 网络编程示例之零:前言
  • StackExchange.Redis帮助类解决方案RedisRepository封装(散列Hash类型数据操作)
  • 【每天读一点英文】gnuhpc注释版:The True Nobility
  • CEPH RGW多 ZONE的配置
  • 【每天读一点英文】gnuhpc:The World As I See It(节选)
  • Java学习随笔之1: Java 语言概述和开发环境
  • iPad - 开发(Universal Applications)
  • Muduo 网络编程示例之一:五个简单 TCP 协议
  • 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES
  • 继续玩转喷墨打印机
  • cookies,sessionStorage和localStorage的区别
  • 51nod 1103【鸽巢原理】
  • 从零实现3D图像引擎:(2)画2D直线不简单
  • Muduo 网络编程示例之二:Boost.Asio 的聊天服务器
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Bootstrap JS插件Alert源码分析
  • css的样式优先级
  • Elasticsearch 参考指南(升级前重新索引)
  • in typeof instanceof ===这些运算符有什么作用
  • JS笔记四:作用域、变量(函数)提升
  • MQ框架的比较
  • mysql 5.6 原生Online DDL解析
  • Mysql数据库的条件查询语句
  • springboot_database项目介绍
  • use Google search engine
  • 模型微调
  • 微信小程序--------语音识别(前端自己也能玩)
  • 我是如何设计 Upload 上传组件的
  • 一个完整Java Web项目背后的密码
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 容器镜像
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • $ git push -u origin master 推送到远程库出错
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (52)只出现一次的数字III
  • (8)STL算法之替换
  • (C语言)逆序输出字符串
  • (二十四)Flask之flask-session组件
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (图)IntelliTrace Tools 跟踪云端程序
  • (原+转)Ubuntu16.04软件中心闪退及wifi消失
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • ***检测工具之RKHunter AIDE
  • .aanva
  • .NET Framework 3.5中序列化成JSON数据及JSON数据的反序列化,以及jQuery的调用JSON
  • .Net IE10 _doPostBack 未定义
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • @Service注解让spring找到你的Service bean
  • [ JavaScript ] JSON方法
  • [ 数据结构 - C++]红黑树RBTree