在2D游戏中一个游戏的渲染部分一般有如下共同的信息:
纹理贴图和精灵
精灵是一种特殊的对象类型.一般是出现在屏幕上的2D和3D图形元素。
在2D游戏中,精灵不仅仅表示角色,还可以表示背景,游戏对象,武器,和任何单个的元素,甚至是能够绘制出来的项
顶点:
定义在游戏图形中的形状其实是一系列点以及它们之间相互连接的边的集合
位置:Postition
颜色:Color
法线向量:Normal vector
贴图坐标: Texture coordinate
在视频游戏中顶点的其它性质包括但不限于:
S-tangent 用于法线映射
Bi-normal 用于发现映射
骨骼重量和索引, 用于骨骼动画
光照映射坐标
每个点的环境光遮罩因子
一般来说我们先定义定点的位置,再来定义其他的性质.
许多渲染效果的工作使用每个像素的数据代替使用每个顶点的数据
我们不能从几何体中直接得出每个像素的数据,这些像素的数据是通过插值计算得来的
向量的定义:
struct Vector2D{float X; float Y;}
struct Vector3D{float X; float Y; floatZ}
一块buffer就是一段有具体尺寸的内存。如果有100char类型的数组 那么就有一块100字节的缓存
如果是intergers型的 那么就可以说有一块整型缓存 大小为4bytes X 100 interger = 400 bytes
一块定点缓存是一个类型为ID3D11Buffer的Direct3D缓存,它用于存储一个网格模型的所有顶点数据
当Direct3D渲染我们的对象时,它通过图形总线来变换缓存信息,通过渲染管线执行必要的操作来最终决定几何图形是否被渲染在屏幕上
该技术决定是否几何图形预先可见,并且只提交那些可见或者潜在可见的图形给图形硬件处理
XMFFLOAT3属性: 定义了一个3D向量
struct XMFLOAT3 {
float x;
float y;
float z;
};
XM表示它来自XNA数学库
FLOAT 表示该结构的内部数据类型
3表示该结构内有多少成员
VertexPos vertices[] = {
DirectX::XMFLOAT3(0.5, 0.5, 0.5),
DirectX::XMFLOAT3(0.5, -0.5, 0.5),
DirectX::XMFLOAT3(-0.5,-0.5, 0.5)
}; //定义定点列表,通过3个顶点来定义三角形
D3D11_BUFFER_DESC vertexDesc; //创建一个描述缓存对象
ZeroMemory(&vertexDesc, sizeof(vertexDesc));
vertexDesc.Usage = D3D11_USAGE_DEFAULT;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.ByteWidth = sizeof(vertexDesc) * 3;
D3D11_SUBRESOURCE_DATA resourceData; //创建子资源,使用它来传递定点数据给缓存创建函数
ZeroMemory(&resourceData, sizeof(resourceData));
resourceData.pSysMem = vertices; //pSysMem是一个已经初始化的指针, 发送给缓存填充的内存
ID3D11Buffer* vertexBuffer;
HRESULT result = d3dDevice_->CreateBuffer(&vertexDesc, &resourceData, &vertexBuffer); //创建缓存
D3D11_SUBRESOURCE_DATA
{
const void * pSystMem; //发送给缓存填充的内存
SysMemPitch 和 SysMemSlice 用于纹理图像
SysMemPicth用于决定纹理每行开始的位置
SysMemSlicePitch决定每行的深度
CreateBuffer来创建缓存 如果CreateBuffer成功 我们就能够在缓存中绘制几何图形了
输入布局(Input Layout):
当我们发送几何图形到显卡上时。为了让Direct3D知道所定义的各种属性,它们的顺序和大小
我们使用输入布局告诉API我们所绘制几何图形的数据的顶点布局
顶点布局:
typedef struct D3D11_INPUT_ELEMENT_DESC
{
LPCSTR SemanticName; //描述元素目的的字符串,例如位置 颜色等
UINT SemanticIndex; //语义索引 用于语义相同但值不相同
DXGI_FORMAT Format; //元素的格式
UINT InputSlot; //输入槽 用于寻找指定的顶点
UINT AlignedByteOffset; //偏移量
D3D11_INPUT_CLASSIFICATION InputSlotClass; //输入槽类型
UINT InstanceDataStepRate; //有多少个实例
} D3D11_INPUT_ELEMENT_DESC;
通过CreateInputLayout所创建:
HRESULT CreateInputLayout(
const D3D11_INPUT_ELEMENT_DESC* pInputElement Descs,
UINT NumElements,
const void* pShaderBytecodewithInputSignature,
SIZE_T BytecodeLength,
ID3D11InputLayout** ppInputLayout
)
第一个参数是顶点元素的数组
第二个是数组元素数量
第三个是有输入标识的已经编译的顶点着色器代码
第四个是着色器字码的尺寸
最后一个是该函数所要创建的对象指针
顶点着色器代码的编译:
HRESULT WINAPI D3DX11CompileFromFileA(LPCSTR pSrcFile, //HLSL着色器代码的编译路径
CONST D3D10_SHADER_MACRO* pDefines, //着色器代码中的全局宏,在应用程序内定义宏
LPD3D10INCLUDE pInclude, //着色器代码源文件中打开或关闭文件
LPCSTR pFunctionName, //编译器入口函数名
LPCSTR pProfile, //着色器模型
UINT Flags1, //编译标识1
UINT Flags2, //编译标识2
ID3DX11ThreadPump* pPump, //pump指针 专门处理多线程
ID3D10Blob** ppShader, //编译完成后节码的内存地址
ID3D10Blob** ppErrorMsgs, //产生错误信息的内存地址
HRESULT* pHResult); //pump的返回值
输入的布局使用CreateInputLayout完成
//实现顶点布局
D3D11_INPUT_ELEMENT_DESC vertexLayout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}
};
unsigned int totalLayoutElements = ARRAYSIZE(vertexLayout);
result = d3dDevice_->CreateInputLayout(vertexLayout, totalLayoutElements, vsBuffer->GetBufferPointer(), vsBuffer->GetBufferSize(), &inputLayout);
vsBuffer->Release();
if (FAILED(result)) {
return; //如果错误 则返回
}
//载入像素着色器
ID3DBlob* psBuffer = 0;
ID3DBlob* errorBuffer = 0;
result = D3DX11CompileFromFile("sampleShader.fx", 0, 0, "PS_Main", "ps_4_0", shaderFlag, 0, 0, &psBuffer, &errorBuffer, 0);
if (FAILED(result)) {
if (errorBuffer != 0) {
OutputDebugStringA((char*)errorBuffer->GetBufferPointer());
errorBuffer->Release();
}
return;
}
if (errorBuffer != 0)
errorBuffer->Release();
result = d3dDevice_->CreatePixelShader(psBuffer->GetBufferPointer(), psBuffer->GetBufferSize(), 0, &solidColorPS);
psBuffer->Release();
if (FAILED(result)) {
result;
}