[DirectX11] 074 Instancing
글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자를 적어주세요. 글의 요약 설명 부분. 150자입니다
목차
Instancing
Shader | |
Render.fx Global.fx |
|
Framework | |
Meshes | |
MeshRender.h .cpp | |
Model | |
ModelAnimator.h .cpp |
fx
Render.fx
Global.fx
메쉬에 적용할 color 추가
ModelAnimator
ModelAnimator.h
더보기
#pragma once
class ModelAnimator
{
public:
ModelAnimator(Shader* shader);
~ModelAnimator();
void Update();
private:
void UpdateTweenMode(UINT index);
void UpdateBlendMode(UINT index);
public:
void Render();
public:
void ReadMesh(wstring file);
void ReadMaterial(wstring file);
void ReadClip(wstring file);
Model* GetModel() { return model; }
void Pass(UINT pass);
Transform* AddTransform();
Transform* GetTransform(UINT index) { return transforms[index]; }
void UpdateTransforms();
UINT GetTransformCount() { return transforms.size(); }
void PlayTweenMode(UINT index, UINT clip, float speed = 1.0f, float takeTime = 1.0f);
void PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2);
void SetBlendAlpha(UINT index, float alpha);
void GetAttachTransform(UINT instance, Matrix* outResult);
private:
void CreateTexture();
void CreateClipTransform(UINT index);
private:
struct ClipTransform
{
Matrix** Transform;
ClipTransform()
{
Transform = new Matrix*[MAX_MODEL_KEYFRAMES];
for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++)
Transform[i] = new Matrix[MAX_MODEL_TRANSFORMS];
}
~ClipTransform()
{
for (UINT i = 0; i < MAX_MODEL_KEYFRAMES; i++)
SafeDeleteArray(Transform[i]);
SafeDeleteArray(Transform);
}
};
ClipTransform* clipTransforms = NULL;
ID3D11Texture2D* texture = NULL;
ID3D11ShaderResourceView* srv = NULL;
private:
struct KeyframeDesc
{
int Clip = 0;
UINT CurrFrame = 0;
UINT NextFrame = 0;
float Time = 0.0f;
float RunningTime = 0.0f;
float Speed = 1.0f;
Vector2 Padding;
}; // keyframeDesc;
struct TweenDesc
{
float TakeTime = 1.0f;
float TweenTime = 0.0f;
float ChangeTime = 0.0f;
float Padding;
KeyframeDesc Curr;
KeyframeDesc Next;
TweenDesc()
{
Curr.Clip = 0;
Next.Clip = -1;
}
} tweenDesc[MAX_MODEL_INSTANCE];
ConstantBuffer* tweenBuffer;
ID3DX11EffectConstantBuffer* sTweenBuffer;
private:
struct BlendDesc
{
UINT Mode = 0;
float Alpha = 0;
Vector2 Padding;
KeyframeDesc Clip[3];
} blendDesc[MAX_MODEL_INSTANCE];
ConstantBuffer* blendBuffer;
ID3DX11EffectConstantBuffer* sBlendBuffer;
private:
Shader* shader;
Model* model;
vector<Transform *> transforms;
Matrix worlds[MAX_MODEL_INSTANCE];
VertexBuffer* instanceBuffer;
private:
Color colors[MAX_MODEL_INSTANCE];
VertexBuffer* instanceBuffer2;
private:
struct CS_InputDesc
{
Matrix Bone;
};
struct CS_OutputDesc
{
Matrix Result;
};
private:
const float frameRate = 30.0f;
float frameTime = 0.0f;
Shader* computeShader;
ID3DX11EffectShaderResourceVariable* sTransformsSRV;
StructuredBuffer* inputWorldBuffer;
ID3DX11EffectShaderResourceVariable* sInputWorldSRV;
StructuredBuffer* inputBoneBuffer;
ID3DX11EffectShaderResourceVariable* sInputBoneSRV;
TextureBuffer* outputBuffer;
ID3DX11EffectUnorderedAccessViewVariable* sOutputUAV;
ID3DX11EffectConstantBuffer* sComputeTweenBuffer;
ID3DX11EffectConstantBuffer* sComputeBlendBuffer;
};
ModelAnimator.cpp
더보기
#include "Framework.h"
#include "ModelAnimator.h"
ModelAnimator::ModelAnimator(Shader * shader)
: shader(shader)
{
model = new Model();
tweenBuffer = new ConstantBuffer(&tweenDesc, sizeof(TweenDesc) * MAX_MODEL_INSTANCE);
sTweenBuffer = shader->AsConstantBuffer("CB_TweenFrame");
blendBuffer = new ConstantBuffer(&blendDesc, sizeof(BlendDesc) * MAX_MODEL_INSTANCE);
sBlendBuffer = shader->AsConstantBuffer("CB_BlendFrame");
instanceBuffer = new VertexBuffer(worlds, MAX_MODEL_INSTANCE, sizeof(Matrix), 1, true);
for (UINT i = 0; i < MAX_MODEL_INSTANCE; i++)
{
colors[i] = Color(1, 1, 1, 1);
colors[i] = Math::RandomColor3();
colors[i].a = 1.0f;
}
instanceBuffer2 = new VertexBuffer(colors, MAX_MODEL_INSTANCE, sizeof(Color), 2, true);
//Create Compute Shader
{
computeShader = new Shader(L"71_GetMultiBones.fx");
inputWorldBuffer = new StructuredBuffer(worlds, sizeof(Matrix), MAX_MODEL_INSTANCE);
sInputWorldSRV = computeShader->AsSRV("InputWorlds");
inputBoneBuffer = new StructuredBuffer(NULL, sizeof(Matrix), MAX_MODEL_TRANSFORMS);
sInputBoneSRV = computeShader->AsSRV("InputBones");
ID3D11Texture2D* texture;
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = MAX_MODEL_TRANSFORMS * 4;
desc.Height = MAX_MODEL_INSTANCE;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
Check(D3D::GetDevice()->CreateTexture2D(&desc, NULL, &texture));
outputBuffer = new TextureBuffer(texture);
SafeRelease(texture);
sOutputUAV = computeShader->AsUAV("Output");
sTransformsSRV = computeShader->AsSRV("TransformsMap");
sComputeTweenBuffer = computeShader->AsConstantBuffer("CB_TweenFrame");
sComputeBlendBuffer = computeShader->AsConstantBuffer("CB_BlendFrame");
}
}
ModelAnimator::~ModelAnimator()
{
SafeDelete(model);
SafeDeleteArray(clipTransforms);
SafeRelease(texture);
SafeRelease(srv);
SafeDelete(tweenBuffer);
SafeDelete(blendBuffer);
SafeDelete(instanceBuffer);
SafeDelete(instanceBuffer2);
SafeDelete(computeShader);
SafeDelete(inputWorldBuffer);
SafeDelete(inputBoneBuffer);
SafeDelete(outputBuffer);
}
void ModelAnimator::Update()
{
if (texture == NULL)
{
for (ModelMesh* mesh : model->Meshes())
mesh->SetShader(shader);
CreateTexture();
Matrix bones[MAX_MODEL_TRANSFORMS];
for (UINT i = 0; i < model->BoneCount(); i++)
bones[i] = model->BoneByIndex(i)->Transform();
inputBoneBuffer->CopyToInput(bones);
}
for (UINT i = 0; i < transforms.size(); i++)
blendDesc[i].Mode == 0 ? UpdateTweenMode(i) : UpdateBlendMode(i);
tweenBuffer->Render();
blendBuffer->Render();
frameTime += Time::Delta();
if (frameTime > (1.0f / frameRate))
{
sComputeTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer());
sComputeBlendBuffer->SetConstantBuffer(blendBuffer->Buffer());
sTransformsSRV->SetResource(srv);
sInputWorldSRV->SetResource(inputWorldBuffer->SRV());
sInputBoneSRV->SetResource(inputBoneBuffer->SRV());
sOutputUAV->SetUnorderedAccessView(outputBuffer->UAV());
computeShader->Dispatch(0, 0, 1, MAX_MODEL_INSTANCE, 1);
outputBuffer->CopyFromOutput();
}
frameTime = fmod(frameTime, (1.0f / frameRate));
if (Keyboard::Get()->Down(VK_SPACE))
{
ID3D11Texture2D* temp = outputBuffer->CopyFromOutput();
FILE* src;
fopen_s(&src, "../src.csv", "w");
Matrix id[MAX_MODEL_TRANSFORMS];
for (UINT y = 0; y < MAX_MODEL_INSTANCE; y++)
{
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(temp, 0, D3D11_MAP_READ, 0, &subResource);
{
void* p = (BYTE *)subResource.pData + y * subResource.RowPitch;
memcpy(id, p, MAX_MODEL_TRANSFORMS * sizeof(Matrix));
}
D3D::GetDC()->Unmap(temp, 0);
for (UINT x = 0; x < MAX_MODEL_TRANSFORMS; x++)
{
Matrix destMatrix = id[x];
fprintf(src, "%f,%f,%f,%f,", destMatrix._11, destMatrix._12, destMatrix._13, destMatrix._14);
fprintf(src, "%f,%f,%f,%f,", destMatrix._21, destMatrix._22, destMatrix._23, destMatrix._24);
fprintf(src, "%f,%f,%f,%f,", destMatrix._31, destMatrix._32, destMatrix._33, destMatrix._34);
fprintf(src, "%f,%f,%f,%f\n", destMatrix._41, destMatrix._42, destMatrix._43, destMatrix._44);
}
}
fclose(src);
}
for (ModelMesh* mesh : model->Meshes())
mesh->Update();
}
void ModelAnimator::UpdateTweenMode(UINT index)
{
TweenDesc& desc = tweenDesc[index];
//현재 애니메이션
{
ModelClip* clip = model->ClipByIndex(desc.Curr.Clip);
desc.Curr.RunningTime += Time::Delta();
float time = 1.0f / clip->FrameRate() / desc.Curr.Speed;
if (desc.Curr.Time >= 1.0f)
{
desc.Curr.RunningTime = 0;
desc.Curr.CurrFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount();
desc.Curr.NextFrame = (desc.Curr.CurrFrame + 1) % clip->FrameCount();
}
desc.Curr.Time = desc.Curr.RunningTime / time;
}
if (desc.Next.Clip > -1)
{
desc.ChangeTime += Time::Delta();
desc.TweenTime = desc.ChangeTime / desc.TakeTime;
if (desc.TweenTime >= 1.0f)
{
desc.Curr = desc.Next;
desc.Next.Clip = -1;
desc.Next.CurrFrame = 0;
desc.Next.NextFrame = 0;
desc.Next.Time = 0;
desc.Next.RunningTime = 0.0f;
desc.ChangeTime = 0.0f;
desc.TweenTime = 0.0f;
}
else
{
ModelClip* clip = model->ClipByIndex(desc.Next.Clip);
desc.Next.RunningTime += Time::Delta();
float time = 1.0f / clip->FrameRate() / desc.Next.Speed;
if (desc.Next.Time >= 1.0f)
{
desc.Next.RunningTime = 0;
desc.Next.CurrFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount();
desc.Next.NextFrame = (desc.Next.CurrFrame + 1) % clip->FrameCount();
}
desc.Next.Time = desc.Next.RunningTime / time;
}
}
}
void ModelAnimator::UpdateBlendMode(UINT index)
{
BlendDesc& desc = blendDesc[index];
for (UINT i = 0; i < 3; i++)
{
ModelClip* clip = model->ClipByIndex(desc.Clip[i].Clip);
desc.Clip[i].RunningTime += Time::Delta();
float time = 1.0f / clip->FrameRate() / desc.Clip[i].Speed;
if (desc.Clip[i].Time >= 1.0f)
{
desc.Clip[i].RunningTime = 0;
desc.Clip[i].CurrFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount();
desc.Clip[i].NextFrame = (desc.Clip[i].CurrFrame + 1) % clip->FrameCount();
}
desc.Clip[i].Time = desc.Clip[i].RunningTime / time;
}
}
void ModelAnimator::Render()
{
sTweenBuffer->SetConstantBuffer(tweenBuffer->Buffer());
sBlendBuffer->SetConstantBuffer(blendBuffer->Buffer());
instanceBuffer->Render();
instanceBuffer2->Render();
for (ModelMesh* mesh : model->Meshes())
mesh->Render(transforms.size());
}
void ModelAnimator::ReadMesh(wstring file)
{
model->ReadMesh(file);
}
void ModelAnimator::ReadMaterial(wstring file)
{
model->ReadMaterial(file);
}
void ModelAnimator::ReadClip(wstring file)
{
model->ReadClip(file);
}
void ModelAnimator::Pass(UINT pass)
{
for (ModelMesh* mesh : model->Meshes())
mesh->Pass(pass);
}
void ModelAnimator::PlayTweenMode(UINT index, UINT clip, float speed, float takeTime)
{
blendDesc[index].Mode = 0;
tweenDesc[index].TakeTime = takeTime;
tweenDesc[index].Next.Clip = clip;
tweenDesc[index].Next.Speed = speed;
}
void ModelAnimator::PlayBlendMode(UINT index, UINT clip, UINT clip1, UINT clip2)
{
blendDesc[index].Mode = 1;
blendDesc[index].Clip[0].Clip = clip;
blendDesc[index].Clip[1].Clip = clip1;
blendDesc[index].Clip[2].Clip = clip2;
}
void ModelAnimator::SetBlendAlpha(UINT index, float alpha)
{
alpha = Math::Clamp(alpha, 0.0f, 2.0f);
blendDesc[index].Alpha = alpha;
}
void ModelAnimator::GetAttachTransform(UINT instance, Matrix * outResult)
{
ID3D11Texture2D* texture = outputBuffer->Result();
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(texture, 0, D3D11_MAP_READ, 0, &subResource);
{
memcpy(outResult, (BYTE *)subResource.pData + (instance * subResource.RowPitch), sizeof(Matrix) * MAX_MODEL_TRANSFORMS);
}
D3D::GetDC()->Unmap(texture, 0);
}
void ModelAnimator::CreateTexture()
{
//Matrix matrix[MAX_MODEL_KEYFRAMES][MAX_MODEL_TRANSFORMS];
clipTransforms = new ClipTransform[model->ClipCount()];
for (UINT i = 0; i < model->ClipCount(); i++)
CreateClipTransform(i);
//Create Texture
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_TEXTURE2D_DESC));
desc.Width = MAX_MODEL_TRANSFORMS * 4;
desc.Height = MAX_MODEL_KEYFRAMES;
desc.ArraySize = model->ClipCount();
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; //16Byte * 4 = 64Byte
desc.Usage = D3D11_USAGE_IMMUTABLE;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
UINT pageSize = MAX_MODEL_TRANSFORMS * 4 * 16 * MAX_MODEL_KEYFRAMES;
//void* p = malloc(pageSize * model->ClipCount());
void* p = VirtualAlloc(NULL, pageSize * model->ClipCount(), MEM_RESERVE, PAGE_READWRITE);
//MEMORY_BASIC_INFORMATION, VirtualQuery
for (UINT c = 0; c < model->ClipCount(); c++)
{
UINT start = c * pageSize;
for (UINT k = 0; k < MAX_MODEL_KEYFRAMES; k++)
{
void* temp = (BYTE *)p + MAX_MODEL_TRANSFORMS * k * sizeof(Matrix) + start;
VirtualAlloc(temp, MAX_MODEL_TRANSFORMS * sizeof(Matrix), MEM_COMMIT, PAGE_READWRITE);
memcpy(temp, clipTransforms[c].Transform[k], MAX_MODEL_TRANSFORMS * sizeof(Matrix));
}
}//for(c)
D3D11_SUBRESOURCE_DATA* subResources = new D3D11_SUBRESOURCE_DATA[model->ClipCount()];
for (UINT c = 0; c < model->ClipCount(); c++)
{
void* temp = (BYTE *)p + c * pageSize;
subResources[c].pSysMem = temp;
subResources[c].SysMemPitch = MAX_MODEL_TRANSFORMS * sizeof(Matrix);
subResources[c].SysMemSlicePitch = pageSize;
}
Check(D3D::GetDevice()->CreateTexture2D(&desc, subResources, &texture));
SafeDeleteArray(subResources);
VirtualFree(p, 0, MEM_RELEASE);
}
//Create SRV
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc;
ZeroMemory(&desc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
desc.Texture2DArray.MipLevels = 1;
desc.Texture2DArray.ArraySize = model->ClipCount();
Check(D3D::GetDevice()->CreateShaderResourceView(texture, &desc, &srv));
}
for (ModelMesh* mesh : model->Meshes())
mesh->TransformsSRV(srv);
}
void ModelAnimator::CreateClipTransform(UINT index)
{
Matrix* bones = new Matrix[MAX_MODEL_TRANSFORMS];
ModelClip* clip = model->ClipByIndex(index);
for (UINT f = 0; f < clip->FrameCount(); f++)
{
for (UINT b = 0; b < model->BoneCount(); b++)
{
ModelBone* bone = model->BoneByIndex(b);
Matrix parent;
Matrix invGlobal = bone->Transform();
D3DXMatrixInverse(&invGlobal, NULL, &invGlobal);
int parentIndex = bone->ParentIndex();
if (parentIndex < 0)
D3DXMatrixIdentity(&parent);
else
parent = bones[parentIndex];
Matrix animation;
ModelKeyframe* frame = clip->Keyframe(bone->Name());
if (frame != NULL)
{
ModelKeyframeData& data = frame->Transforms[f];
Matrix S, R, T;
D3DXMatrixScaling(&S, data.Scale.x, data.Scale.y, data.Scale.z);
D3DXMatrixRotationQuaternion(&R, &data.Rotation);
D3DXMatrixTranslation(&T, data.Translation.x, data.Translation.y, data.Translation.z);
animation = S * R * T;
}
else
{
D3DXMatrixIdentity(&animation);
}
bones[b] = animation * parent;
clipTransforms[index].Transform[f][b] = invGlobal * bones[b];
}//for(b)
}//for(f)
}
Transform * ModelAnimator::AddTransform()
{
Transform* transform = new Transform();
transforms.push_back(transform);
return transform;
}
void ModelAnimator::UpdateTransforms()
{
for (UINT i = 0; i < transforms.size(); i++)
memcpy(worlds[i], transforms[i]->World(), sizeof(Matrix));
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(instanceBuffer->Buffer(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
{
memcpy(subResource.pData, worlds, sizeof(Matrix) * MAX_MESH_INSTANCE);
}
D3D::GetDC()->Unmap(instanceBuffer->Buffer(), 0);
inputWorldBuffer->CopyToInput(worlds);
}
MeshRender
MeshRender.h
더보기
#pragma once
#define MAX_MESH_INSTANCE 500
class MeshRender
{
public:
MeshRender(Shader* shader, Mesh* mesh);
~MeshRender();
Mesh* GetMesh() { return mesh; }
void Update();
void Render();
void Pass(UINT val) { mesh->Pass(val); }
Transform* AddTransform();
Transform* GetTransform(UINT index) { return transforms[index]; }
void UpdateTransforms();
private:
Mesh* mesh;
vector<Transform *> transforms;
Matrix worlds[MAX_MESH_INSTANCE];
VertexBuffer* instanceBuffer;
};
MeshRender.cpp
더보기
#include "Framework.h"
#include "MeshRender.h"
MeshRender::MeshRender(Shader * shader, Mesh * mesh)
: mesh(mesh)
{
Pass(0);
mesh->SetShader(shader);
for (UINT i = 0; i < MAX_MESH_INSTANCE; i++)
D3DXMatrixIdentity(&worlds[i]);
instanceBuffer = new VertexBuffer(worlds, MAX_MESH_INSTANCE, sizeof(Matrix), 1, true);
}
MeshRender::~MeshRender()
{
for (Transform* transform : transforms)
SafeDelete(transform);
SafeDelete(instanceBuffer);
SafeDelete(mesh);
}
void MeshRender::Update()
{
mesh->Update();
}
void MeshRender::Render()
{
instanceBuffer->Render();
mesh->Render(transforms.size());
}
Transform * MeshRender::AddTransform()
{
Transform* transform = new Transform();
transforms.push_back(transform);
return transform;
}
void MeshRender::UpdateTransforms()
{
for (UINT i = 0; i < transforms.size(); i++)
memcpy(worlds[i], transforms[i]->World(), sizeof(Matrix));
D3D11_MAPPED_SUBRESOURCE subResource;
D3D::GetDC()->Map(instanceBuffer->Buffer(), 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
{
memcpy(subResource.pData, worlds, sizeof(Matrix) * MAX_MESH_INSTANCE);
}
D3D::GetDC()->Unmap(instanceBuffer->Buffer(), 0);
}
실행화면
각 매쉬별로 다른 색을 지정해서 넣을 수 있다.
'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 078~79 Point Lighting, HLSL [flatten] [branch] (0) | 2023.03.21 |
---|---|
[DirectX11] 075~77 Lighting, HLSL (0) | 2023.03.18 |
[DirectX11] 071~73 Get MultiBones (0) | 2023.03.15 |
[DirectX11] 070 OBB(Oriented Bounding Box) collision (3) | 2023.03.14 |
[DirectX11] 069 Collider (0) | 2023.03.13 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 078~79 Point Lighting, HLSL [flatten] [branch]
[DirectX11] 078~79 Point Lighting, HLSL [flatten] [branch]
2023.03.21 -
[DirectX11] 075~77 Lighting, HLSL
[DirectX11] 075~77 Lighting, HLSL
2023.03.18 -
[DirectX11] 071~73 Get MultiBones
[DirectX11] 071~73 Get MultiBones
2023.03.15 -
[DirectX11] 070 OBB(Oriented Bounding Box) collision
[DirectX11] 070 OBB(Oriented Bounding Box) collision
2023.03.14