1、D3D库的初始化
//初始化库
IDirect3D9* d3d = 0;
d3d = Direct3DCreate9(D3D_SDK_VERSION);
2、设备性能检查
//检查设备能力
D3DCAPS9 devCaps;
HRESULT hResult;
hResult = d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &devCaps);
//D3DDEVTYPE_REF
int vp = 0;
if (hResult && (devCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT))
{
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
3、多重采样设置
D3DMULTISAMPLE_TYPE multiType = D3DMULTISAMPLE_NONE;
multiType = D3DMULTISAMPLE_8_SAMPLES;
DWORD quality;
d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
D3DFMT_A8R8G8B8, true, D3DMULTISAMPLE_8_SAMPLES, &quality);
4、创建设备
//创建设备
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.Windowed = windowed;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.MultiSampleType = multiType;
d3dpp.MultiSampleQuality = quality;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
hResult = d3d->CreateDevice(D3DADAPTER_DEFAULT, devtype, hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, dev);
if (FAILED(hResult))
{
d3d->Release();
d3d = 0;
return false;
}
5、锁定和修改后备缓冲区
IDirect3DSurface9* surface;
//1、通过swapchain获取后备缓冲区
IDirect3DSwapChain9* chain;
(*dev)->GetSwapChain(0, &chain);
chain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface);
//2、通过设备获取后备缓冲区
(*dev)->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &surface);
D3DSURFACE_DESC sDesc;
surface->GetDesc(&sDesc);
D3DLOCKED_RECT lockedRect;
surface->LockRect(&lockedRect,0,0);
//直接按像素修改后备缓冲区
DWORD* imageData = (DWORD*)lockedRect.pBits;
for (int i = 0; i < sDesc.Height; i++)
{
for (int j = 0; j < sDesc.Width; j++)
{
int index = i * lockedRect.Pitch / 4 + j;
imageData[index] = 0xffff0000; // red
}
}
surface->UnlockRect();
surface->Release();
6、D3D中使用的COM对象
IDirect3D9
IDirect3DDevice9
IDirect3DSurface9
IDirect3DSwapChain9
IDirect3DVertexBuffer9
IDirect3DIndexBuffer9
IDirect3DTexture9
ID3DXBuffer
ID3DXMesh
ID3DXBaseMesh
7、枚举常量
//像素格式
D3DFMT_A8R8G8B8
D3DFMT_X8R8G8B8
D3DFMT_R8G8B8
//深度缓冲区和蒙版格式
D3DFMT_D24S8
D3DFMT_D24X8
D3DFMT_D32
//内存池
D3DPOOL_DEFAULT 高性能
D3DPOOL_MANAGED D3D库管理
//缓存使用方式
D3DUSAGE_WRITEONLY
D3DUSAGE_DYNAMIC 非动态的缓存使用显存,处理速度快,
但应用程序读写慢,应该在软件初始化时设置一次
D3DUSAGE_POINTS
//索引格式,
D3DFMT_INDEX16 常用
D3DFMT_INDEX32
8、顶点格式和三大变换
//灵活顶点格式,需要与顶点结构体的定义保持一致
DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE; //带颜色
fvf = D3DFVF_XYZ | D3DFVF_NORMAL| D3DFVF_TEX1; //带纹理和法向量
//世界坐标系
D3DXMatrixTranslation(&pyramMatrix, 5, 5, 5);
pDevice->SetTransform(D3DTS_WORLD, &pyramMatrix);
//视图坐标系
static float angle = (3.0f * D3DX_PI) / 2.0f;
static float cameraHeight = 0.0f;
static float cameraHeightDirection = 5.0f;
D3DXVECTOR3 position(cosf(angle) * 10.0f, cameraHeight, sinf(angle) * 10.0f);
// the camera is targetted at the origin of the world
D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
// the worlds up vector
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX V;
D3DXMatrixLookAtLH(&V, &position, &target, &up);
pDevice->SetTransform(D3DTS_VIEW, &V);
//投影坐标系
D3DXMATRIX project;
D3DXMatrixPerspectiveFovLH(&project, D3DX_PI * 0.5, 640 / (float)480, 1.0f, 1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &project);
9、渲染状态
//剔除规则
pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
//填充模式 D3DFILL_WIREFRAME
pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
//着色模式 D3DSHADE_FLAT
pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
10、顶点缓冲区和索引缓冲区
IDirect3DVertexBuffer9* vBuffer = NULL;
HRESULT hr;
hr = pDevice->CreateVertexBuffer(3 * sizeof(Vertex),
D3DUSAGE_WRITEONLY,
Vertex::fvf, D3DPOOL_MANAGED, &vBuffer, NULL);
IDirect3DIndexBuffer9* IB = 0;
hr = pDevice->CreateIndexBuffer(
36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&IB,
0);
//读写缓冲区内容
Vertex* vertex;
vBuffer->Lock(0, 0, (void**)&vertex, 0);
......
vBuffer->Unlock();
WORD* indices = 0;
IB->Lock(0, 0, (void**)&indices, 0);
......
IB->Unlock();
//获取属性信息
D3DINDEXBUFFER_DESC indexDesc;
IB->GetDesc(&indexDesc);
D3DVERTEXBUFFER_DESC verDesc;
vBuffer->GetDesc(&verDesc);
11、绘图
pDevice->BeginScene();
pDevice->SetStreamSource(0, vBuffer, 0, sizeof(Vertex));
pDevice->SetFVF(Vertex::fvf);
pDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
//使用索引
pDevice->SetIndices(IB);
pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
pDevice->EndScene();
pDevice->Present(0, 0, 0, 0);
12、Mesh三维网格
ID3DXMesh* obj[5] = {0,0,0,0,0};
//使用内置函数创建Mesh
D3DXCreateTeapot(pDevice, &obj[0], NULL);
D3DXCreateBox(pDevice, 2, 3, 5, &obj[1], NULL);
D3DXCreateCylinder(
pDevice,
1.0f, // radius at negative z end
1.0f, // radius at positive z end
3.0f, // length of cylinder
10, // slices
10, // stacks
&obj[2],
0);
D3DXCreateTorus(
pDevice,
1.0f, // inner radius
3.0f, // outer radius
10, // sides
10, // rings
&obj[3],
0);
D3DXCreateSphere(
pDevice,
1.0f, // radius
10, // slices
10, // stacks
&obj[4],
0);
D3DXCreatePolygon(...);
D3DXCreateText(...);
//绘图Mesh
obj[i]->DrawSubset(0);
获取Mesh的信息
D3DXCreateTeapot(pDevice, &obj[0], NULL);
//ID3DXMesh 的基类 ID3DXBaseMesh
//ID3DXMesh 只支持 Triangle List 类型
IDirect3DVertexBuffer9* pVertex;
obj[0]->GetVertexBuffer(&pVertex);
D3DVERTEXBUFFER_DESC teapotDesc;
pVertex->GetDesc(&teapotDesc);
IDirect3DIndexBuffer9* pIndex;
obj[0]->GetIndexBuffer(&pIndex);
//创建空的Mesh,手工填充顶点和索引数据
hr = D3DXCreateMeshFVF(
12,
24,
D3DXMESH_MANAGED,
Vertex::FVF,
Device,
&obj[0]);
BYTE* pData;
obj[0]->LockVertexBuffer(D3DLOCK_READONLY, (void**)&pData);
obj[0]->UnlockVertexBuffer();
obj[0]->LockIndexBuffer(D3DLOCK_READONLY, (void**)&pData);
obj[0]->UnlockIndexBuffer();
DWORD fvf = obj[0]->GetFVF(); //顶点格式
DWORD nVertices = obj[0]->GetNumVertices(); //顶点数量
DWORD nBytePerV = obj[0]->GetNumBytesPerVertex(); //每个顶点字节数
DWORD nFaces = obj[0]->GetNumFaces(); //三角形数量
子集和属性缓冲区
一个Mesh可包含多个子集,子集是使用相同属性渲染的一组三角形集合。属性是材质、纹理和渲染状态。每个三角型有一个属性ID,有相同属性ID的三角形属于同一个子集。
DWORD *buff;
obj[0]->LockAttributeBuffer(D3DLOCK_READONLY, &buff);
DWORD attID = buff[0];
attID = buff[nFaces-1];
obj[0]->UnlockAttributeBuffer();
属性表和邻接信息表
ID3DXMesh *optMesh;
obj[0]->Optimize(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT |
D3DXMESHOPT_STRIPREORDER | D3DXMESHOPT_VERTEXCACHE, NULL, NULL,
NULL, NULL,&optMesh);
//obj[0]->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT |
// D3DXMESHOPT_STRIPREORDER | D3DXMESHOPT_VERTEXCACHE, NULL, NULL,
// NULL, NULL);
//D3DXMESHOPT_ATTRSORT 产生 Mesh 的 AttributeTable
DWORD numSubset = 0;
optMesh->GetAttributeTable(0, &numSubset);
//每个子集对于一项
D3DXATTRIBUTERANGE* table = new D3DXATTRIBUTERANGE[numSubset];
optMesh->GetAttributeTable(table, &numSubset);
obj[0]->SetAttributeTable(table, numSubset);
//邻接信息表,每一项对应一个邻接三角形,每个三角形都有三项。
//-1表示没有邻接三角形。
int adjSize = optMesh->GetNumFaces() * 3;
DWORD *adjInfo = new DWORD[adjSize];
optMesh->GenerateAdjacency(0.001f, adjInfo);
ID3DXMesh* clone;
optMesh->CloneMeshFVF(optMesh->GetOptions(),
//增加纹理坐标属性
D3DFVF_XYZ| D3DFVF_NORMAL| D3DFVF_TEX1,
pDevice,&clone);
手工创建Mesh
需要填充顶点、索引和属性缓冲区三种信息。
hr = D3DXCreateMeshFVF( 12, 24, D3DXMESH_MANAGED,
Vertex::FVF, Device, &Mesh);
Vertex* v = 0;
Mesh->LockVertexBuffer(0, (void**)&v);
//填充顶点缓冲区
Mesh->UnlockVertexBuffer();
WORD* i = 0;
Mesh->LockIndexBuffer(0, (void**)&i);
//填充索引缓冲区
Mesh->UnlockIndexBuffer();
DWORD* attributeBuffer = 0;
Mesh->LockAttributeBuffer(0, &attributeBuffer);
//指定每个三角形所属的子集
//attributeBuffer[a] = 0;
Mesh->UnlockAttributeBuffer();
//产生邻接信息和属性表
std::vector<DWORD> adjacencyBuffer(Mesh->GetNumFaces() * 3);
Mesh->GenerateAdjacency(0.0f, &adjacencyBuffer[0]);
hr = Mesh->OptimizeInplace(
D3DXMESHOPT_ATTRSORT |
D3DXMESHOPT_COMPACT |
D3DXMESHOPT_VERTEXCACHE,
&adjacencyBuffer[0],
0, 0, 0);
//另一种方式
D3DVERTEXELEMENT9 velement[MAX_FVF_DECL_SIZE];
D3DXDeclaratorFromFVF(D3DFVF_XYZ | D3DFVF_NORMAL, velement);
ID3DXMesh *mesh;
D3DXCreateMesh(12, 24, D3DXMESH_MANAGED,
velement,
pDevice,
&mesh);
从文件中加载Mesh模型
ID3DXMesh* shipMesh;
ID3DXBuffer* shipAdj;
ID3DXBuffer* shipMaterial;
vector<D3DMATERIAL9> shipMaterials;
std::vector<IDirect3DTexture9*> shipTextures;
DWORD numMaterail = 0;
HRESULT hr = D3DXLoadMeshFromX(L"bigship1.x", D3DXMESH_MANAGED, pDevice,
&shipAdj, &shipMaterial, NULL, &numMaterail, &shipMesh);
//材质,每个子集对应一项
if (numMaterail > 0 && shipMaterial != nullptr)
{
D3DXMATERIAL* m = (D3DXMATERIAL*)shipMaterial->GetBufferPointer();
for (int i = 0; i < numMaterail; ++i)
{
m[i].MatD3D.Ambient = m[i].MatD3D.Diffuse; //没有包含环境光
shipMaterials.push_back(m[i].MatD3D);
if (m[i].pTextureFilename != 0) //纹理文件名
{
IDirect3DTexture9* tex = 0;
D3DXCreateTextureFromFileA(pDevice, m[i].pTextureFilename, &tex);
shipTextures.push_back(tex);
}
}
}
shipMaterial->Release();
//计算顶点向量
if (!(shipMesh->GetFVF() & D3DFVF_NORMAL))
{
ID3DXMesh* temp = nullptr;
shipMesh->CloneMeshFVF(shipMesh->GetOptions(),
shipMesh->GetFVF() | D3DFVF_NORMAL, pDevice, &temp);
D3DXComputeNormals(temp, (DWORD*)shipAdj->GetBufferPointer());
shipMesh->Release();
shipMesh = temp;
}
//优化Mesh模型
shipMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)shipAdj->GetBufferPointer(), NULL, NULL, NULL);
shipAdj->Release();
渐进式网格progressive mesh
ID3DXPMesh* pMesh = 0;
std::vector<D3DMATERIAL9> shipMaterials;
std::vector<IDirect3DTexture9*> shipTextures;
ID3DXMesh* SphereMesh = 0;
ID3DXMesh* BoxMesh = 0;
shipMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
(DWORD*)shipAdj->GetBufferPointer(),
(DWORD*)shipAdj->GetBufferPointer(), NULL, NULL);
//使用优化后的邻接表
hr = D3DXGeneratePMesh(shipMesh, (DWORD*)shipAdj->GetBufferPointer(),
NULL, NULL, 1, D3DXMESHSIMP_FACE, &pMesh);
pMesh->SetNumFaces(pMesh->GetMaxFaces());
BYTE* vb = 0;
shipMesh->LockVertexBuffer(0, (void**)&vb);
D3DXVECTOR3 center;
float radius;
hr = D3DXComputeBoundingSphere(
(D3DXVECTOR3*)vb,
shipMesh->GetNumVertices(),
D3DXGetFVFVertexSize(mesh->GetFVF()),
¢er,
&radius);
D3DXVECTOR3 _min, _max;
hr = D3DXComputeBoundingBox(
(D3DXVECTOR3*)vb,
mesh->GetNumVertices(),
D3DXGetFVFVertexSize(mesh->GetFVF()),
&_min,
&_max);
mesh->UnlockVertexBuffer();
//创建sphere Mesh
D3DXCreateSphere(
pDevice,
radius,
20,
20,
&SphereMesh,
0);
//创建 box mesh
D3DXCreateBox(
pDevice,
_max.x - _min.x,
_max.y - _min.y,
_max.z - _min.z,
&BoxMesh,
0);
//绘制
for (int i = 0; i < shipMaterials.size(); i++)
{
// draw pmesh
pDevice->SetMaterial(&shipMaterials[i]);
if(shipTextures.size()>i+1)
pDevice->SetTexture(0, shipTextures[i]);
pMesh->DrawSubset(i);
// draw wireframe outline
pDevice->SetMaterial(&d3d::YELLOW_MTRL);
pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
pMesh->DrawSubset(i);
pDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
}
pDevice->SetMaterial(& pyramMaterial);
pDevice->SetTexture(0, 0); // disable texture
pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
//pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
//pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
//if (RenderBoundingSphere)
SphereMesh->DrawSubset(0);
//else
//BoxMesh->DrawSubset(0);
pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
13、颜色
D3DCOLOR color; //字节序 a,r, g, b;
color = D3DCOLOR_ARGB(255, 255, 0, 0);
D3DCOLORVALUE value{ 1.0f,0,0,1.0f }; //r, g, b, a;
D3DXCOLOR xcolor(color); //r, g, b, a 与 D3DCOLORVALUE 可互换
D3DXCOLOR xcolor2(value);
顶点格式: D3DFVF_XYZ | D3DFVF_DIFFUSE
//启动顶点颜色时,需要关闭光照
pDevice->SetRenderState(D3DRS_LIGHTING, false);
//启用着色模式 D3DSHADE_FLAT
pDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
14、灯光和材质
三种类型的光,每种光都包含光的三种成分。材质是物体对光的每种成分的反射率。三角形共顶点的法向量可能不一致,可以取三角形的法向量。
//方向光
D3DLIGHT9 dirLight;
::ZeroMemory(&dirLight, sizeof(dirLight));
dirLight.Type = D3DLIGHT_DIRECTIONAL;
dirLight.Diffuse = d3d::WHITE; //漫反射光 D3DCOLORVALUE
dirLight.Specular = d3d::WHITE * 0.3f; //镜面反射光
dirLight.Ambient = d3d::WHITE * 0.6f; //环境光
dirLight.Direction = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
pDevice->SetLight(0, &dirLight);
//点光源
D3DXCOLOR c = d3d::WHITE;
D3DLIGHT9 pointLight;
pointLight.Type = D3DLIGHT_POINT;
pointLight.Ambient = c * 0.6f;
pointLight.Diffuse = c;
pointLight.Specular = c * 0.6f;
pointLight.Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
pointLight.Range = 1000.0f; //有效范围
pointLight.Falloff = 1.0f;
pointLight.Attenuation0 = 1.0f; //衰减系数
pointLight.Attenuation1 = 0.0f;
pointLight.Attenuation2 = 0.0f;
pDevice->SetLight(1, &pointLight);
//pDevice->LightEnable(0, true);
//聚光灯
D3DLIGHT9 spotLight ;
spotLight.Type = D3DLIGHT_SPOT;
spotLight.Ambient = c * 0.0f;
spotLight.Diffuse = c;
spotLight.Specular = c* 0.6f;
spotLight.Position = D3DXVECTOR3(0.0f, 0.0f, -5.0f);
spotLight.Direction = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
spotLight.Range = 1000.0f;
spotLight.Falloff = 1.0f;
spotLight.Attenuation0 = 1.0f;
spotLight.Attenuation1 = 0.0f;
spotLight.Attenuation2 = 0.0f;
spotLight.Theta = 0.4f;
spotLight.Phi = 0.9f;
//
// Set and Enable spotlight.
//
pDevice->SetLight(2, &spotLight);
//启用镜面反射光
pDevice->SetRenderState(D3DRS_SPECULARENABLE, true);
//打开1号灯
pDevice->LightEnable(1, true);
D3DMATERIAL9 pyramMaterial;
pyramMaterial.Ambient = d3d::WHITE;
pyramMaterial.Diffuse = d3d::RED;
pyramMaterial.Specular = d3d::WHITE;
pyramMaterial.Emissive = d3d::BLACK; //自发光
pyramMaterial.Power = 5.0f; //镜面光增强系数
pDevice->SetMaterial(&pyramMaterial);
//顶点的最终颜色可以直接指定颜色(需要关闭灯光),也可以通过
//灯光、材质、纹理以及顶点的法向量计算(需要开启灯光)。
pDevice->SetRenderState(D3DRS_LIGHTING, true);
pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
15、纹理
纹理是可以映射到三角形的像素矩阵。纹理应用在最后的栅格化阶段,由于大小不一致,使用三种过滤器。放大、缩小和多级纹理过滤器。
fvf = D3DFVF_XYZ | D3DFVF_NORMAL| D3DFVF_TEX1;
D3DXCreateTextureFromFile(pDevice, L"crate.jpg", &texture);
//缩小、放大过滤器
pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
//D3DTEXF_POINT; D3DTEXF_NONE;
//D3DTEXF_ANISOTROPIC 时需要设置各向异性级别
pDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 3);
//多级渐远纹理过滤器
//D3DTEXF_POINT; D3DTEXF_NONE;
pDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
//纹理的寻址方式
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
//D3DTADDRESS_MIRROR; 镜像
//D3DTADDRESS_CLAMP; 夹取
//D3DTADDRESS_WRAP; 平铺
//D3DTADDRESS_BORDER; 边框,需要设置边框颜色
pDevice->SetSamplerState(0, D3DSAMP_BORDERCOLOR, D3DCOLOR_ARGB(255, 120, 125, 10));
pDevice->SetTexture(0, texture); //设置纹理
......
pDevice->SetTexture(0, 0); //关闭纹理



16、像素混合
// 启用像素融合
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
OutputPixel = SourcePixel * SourceBlendFactor + DestPixel * DestBlendFactor
源像素为将写入后备缓冲器的像素值, 目标像素为当前在后备缓冲区的像素值。
//设置源像素混合系数
pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
//设置目标像素混合系数
pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
//D3DBLEND_ZERO , D3DBLEND_ONE
//D3DBLEND_SRCCOLOR , D3DBLEND_INVSRCCOLOR
//D3DBLEND_DESTCOLOR ,D3DBLEND_INVDESTCOLOR
//D3DBLEND_SRCALPHA(默认的源像素混合系数) ,D3DBLEND_INVSRCALPHA(默认的目标像素混合系数)
//D3DBLEND_DESTALPHA ,D3DBLEND_INVDESTALPHA
//D3DBLEND_SRCALPHASAT (f、f、f、1); f = min(As, 1 - Ad)
Alpha值的来源可以从顶点的颜色、材质中通过着色模式计算获得,也可以通过纹理中的Alpha通道,获得每个像素的Alpha值。默认情况下,优先使用纹理的alpha通道,不存在则从顶点颜色中获取。可以通过函数直接指定Alpha值来源。
//使用颜色、材质
pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
//使用纹理的Alpha通道,DDS文件格式可包含Alpha通道数据
pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
17、摄像机
D3DXVECTOR3 position(0, 10, 0); //摄像机上移动10.
D3DXVECTOR3 target(0.0f, 10.0f, 10.0f);
D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
D3DXMATRIX v1;
D3DXMatrixLookAtLH(&v1, &position, &target, &up);
D3DXMATRIX v2;
D3DXMatrixTranslation(&v2, 0, -10, 0);//把场景中的所有物体下移10
//v1==v2
D3DXVECTOR3 up2(0.0f, -1.0f, 0.0f);//上方向沿X轴顺时针旋转180°。
D3DXMATRIX v3;
D3DXMatrixLookAtLH(&v3, &position, &target, &up2);
D3DXMATRIX v4,v5;
D3DXMatrixRotationX(&v4, -D3DX_PI);//把场景中的所有物体逆时针旋转180°
D3DXMatrixMultiply(&v5, &v2, &v4);
//v3==v5
18、文本显示
D3D提供的ID3DXFont接口使用GDI进行文本绘制,速度稍慢,但支持复杂的字体和格式化。
ID3DXFont* d3dFont;
D3DXFONT_DESC fontDesc;
fontDesc.Height = 25; // in logical units
fontDesc.Width = 12; // in logical units
fontDesc.Weight = 500; // boldness, range 0(light) - 1000(bold)
fontDesc.Italic = false;
fontDesc.CharSet = DEFAULT_CHARSET;
fontDesc.Quality = 0;
fontDesc.OutputPrecision = 0;
fontDesc.MipLevels = 0;
fontDesc.PitchAndFamily = 0;
wcscpy_s(fontDesc.FaceName, L"Times New Roman"); // font style
ZeroMemory(&fontDesc, sizeof(D3DXFONT_DESC));
HRESULT hr=D3DXCreateFontIndirect(pDevice, &fontDesc, &d3dFont);
RECT rect{ 0,0,width,height };
d3dFont->DrawTextW(NULL, L"TEXT TO DRAW", -1, &rect, DT_TOP | DT_LEFT,0XFF00FF00);
19、拾取
当用户在窗口范围内点击时,如何判读点击位置选中了三维空间中的一个模型?

首先将鼠标位置(x,y)映射到透视投影窗口的p点。先后经过视口变换的逆变换,透视投影变换的逆变换。由于没有深度信息,只需要进行缩放和平移操作。
Ray CalcPickingRay(IDirect3DDevice9* device, int x, int y)
{
float px = 0.0f, py = 0.0f;
D3DVIEWPORT9 vp;
device->GetViewport(&vp);
D3DXMATRIX proj;
device->GetTransform(D3DTS_PROJECTION, &proj);
px = (((2.0f * x) / vp.Width) - 1.0f) / proj(0, 0);
py = (((-2.0f * y) / vp.Height) + 1.0f) / proj(1, 1);
Ray ray;
ray._origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
ray._direction = D3DXVECTOR3(px, py, 1.0f);
return ray;
}
然后计算原点到p点的射线与各个模型是否相交。由于射线处于视图空间,为简便计算,将射线变换回世界空间,要用到视图变换的逆变换。
void TransformRay(Ray* ray, D3DXMATRIX* T)
{
// transform the ray's origin, w = 1.
D3DXVec3TransformCoord(
&ray->_origin,
&ray->_origin,
T);
// transform the ray's direction, w = 0.
D3DXVec3TransformNormal(
&ray->_direction,
&ray->_direction,
T);
// normalize the direction
D3DXVec3Normalize(&ray->_direction, &ray->_direction);
}
其中,T为视图变换矩阵的逆矩阵。
// transform the ray to world space
D3DXMATRIX view;
sDemo->pDevice->GetTransform(D3DTS_VIEW, &view);
D3DXMATRIX viewInverse;
D3DXMatrixInverse(&viewInverse, 0, &view);
相交即计算球体中心点到射线距离等于半径的点。为一元二次方程至少有一个大于等于0的解。
bool RaySphereIntTest(Ray* ray, BoundingSphere* sphere)
{
D3DXVECTOR3 v = ray->_origin - sphere->_center;
float b = 2.0f * D3DXVec3Dot(&ray->_direction, &v);
float c = D3DXVec3Dot(&v, &v) - (sphere->_radius * sphere->_radius);
// find the discriminant
float discriminant = (b * b) - (4.0f * c);
// test for imaginary number
if (discriminant < 0.0f)
return false;
discriminant = sqrtf(discriminant);
float s0 = (-b + discriminant) / 2.0f;
float s1 = (-b - discriminant) / 2.0f;
// if a solution is >= 0, then we intersected the sphere
if (s0 >= 0.0f || s1 >= 0.0f)
return true;
return false;
}
一个例子的源代码下载地址:
D3D9固定功能渲染流水线演示实例资源
https://download.youkuaiyun.com/download/eamon100/87723692
本文详细介绍了Direct3D9的渲染流程,包括库的初始化、设备性能检查、多重采样设置、创建设备、锁定和修改后备缓冲区、COM对象的使用、枚举常量、顶点格式和三大变换、渲染状态、顶点缓冲区和索引缓冲区、Mesh三维网格的创建和操作、颜色处理、灯光和材质、纹理应用、像素混合、摄像机设置,以及拾取和文本显示等关键概念和技术。
3970

被折叠的 条评论
为什么被折叠?



