535 lines
16 KiB
C++
535 lines
16 KiB
C++
#include "wiHairParticle.h"
|
|
#include "wiRenderer.h"
|
|
#include "wiResourceManager.h"
|
|
#include "wiLoader.h"
|
|
#include "wiMath.h"
|
|
#include "wiFrustum.h"
|
|
#include "wiRandom.h"
|
|
#include "ResourceMapping.h"
|
|
#include "wiArchive.h"
|
|
#include "ShaderInterop.h"
|
|
|
|
using namespace std;
|
|
using namespace wiGraphicsTypes;
|
|
|
|
VertexLayout *wiHairParticle::il = nullptr;
|
|
VertexShader *wiHairParticle::vs = nullptr;
|
|
PixelShader *wiHairParticle::ps[],*wiHairParticle::qps[];
|
|
GeometryShader *wiHairParticle::gs = nullptr,*wiHairParticle::qgs = nullptr;
|
|
ComputeShader *wiHairParticle::cs_RESET = nullptr;
|
|
ComputeShader *wiHairParticle::cs_CULLING = nullptr;
|
|
DepthStencilState *wiHairParticle::dss = nullptr;
|
|
RasterizerState *wiHairParticle::rs = nullptr, *wiHairParticle::ncrs = nullptr;
|
|
BlendState *wiHairParticle::bs = nullptr;
|
|
int wiHairParticle::LOD[3];
|
|
|
|
wiHairParticle::wiHairParticle()
|
|
{
|
|
cb = nullptr;
|
|
vb = nullptr;
|
|
ib = nullptr;
|
|
name = "";
|
|
densityG = "";
|
|
lenG = "";
|
|
length = 0;
|
|
count = 0;
|
|
material = nullptr;
|
|
object = nullptr;
|
|
materialName = "";
|
|
}
|
|
wiHairParticle::wiHairParticle(const std::string& newName, float newLen, int newCount
|
|
, const std::string& newMat, Object* newObject, const std::string& densityGroup, const std::string& lengthGroup)
|
|
{
|
|
cb = nullptr;
|
|
vb = nullptr;
|
|
ib = nullptr;
|
|
drawargs = nullptr;
|
|
name=newName;
|
|
densityG=densityGroup;
|
|
lenG=lengthGroup;
|
|
length=newLen;
|
|
count=newCount;
|
|
material=nullptr;
|
|
object = newObject;
|
|
materialName = newMat;
|
|
XMStoreFloat4x4(&OriginalMatrix_Inverse, XMMatrixInverse(nullptr, object->getMatrix()));
|
|
for (MeshSubset& subset : object->mesh->subsets)
|
|
{
|
|
if (!newMat.compare(subset.material->name)) {
|
|
material = subset.material;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (material)
|
|
{
|
|
Generate();
|
|
}
|
|
}
|
|
|
|
|
|
void wiHairParticle::CleanUp()
|
|
{
|
|
points.clear();
|
|
SAFE_DELETE(cb);
|
|
SAFE_DELETE(vb);
|
|
SAFE_DELETE(ib);
|
|
SAFE_DELETE(drawargs);
|
|
}
|
|
|
|
void wiHairParticle::CleanUpStatic()
|
|
{
|
|
SAFE_DELETE(il);
|
|
SAFE_DELETE(vs);
|
|
for (int i = 0; i < SHADERTYPE_COUNT; ++i)
|
|
{
|
|
SAFE_DELETE(ps[i]);
|
|
SAFE_DELETE(qps[i]);
|
|
}
|
|
SAFE_DELETE(gs);
|
|
SAFE_DELETE(qgs);
|
|
SAFE_DELETE(cs_RESET);
|
|
SAFE_DELETE(cs_CULLING);
|
|
SAFE_DELETE(dss);
|
|
SAFE_DELETE(rs);
|
|
SAFE_DELETE(ncrs);
|
|
SAFE_DELETE(bs);
|
|
}
|
|
void wiHairParticle::LoadShaders()
|
|
{
|
|
|
|
VertexLayoutDesc layout[] =
|
|
{
|
|
{ "POSITION", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "NORMAL", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "TANGENT", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 },
|
|
};
|
|
UINT numElements = ARRAYSIZE(layout);
|
|
VertexShaderInfo* vsinfo = static_cast<VertexShaderInfo*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassVS.cso", wiResourceManager::VERTEXSHADER, layout, numElements));
|
|
if (vsinfo != nullptr) {
|
|
vs = vsinfo->vertexShader;
|
|
il = vsinfo->vertexLayout;
|
|
}
|
|
|
|
for (int i = 0; i < SHADERTYPE_COUNT; ++i)
|
|
{
|
|
SAFE_INIT(ps[i]);
|
|
SAFE_INIT(qps[i]);
|
|
}
|
|
|
|
ps[SHADERTYPE_DEPTHONLY] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassPS_alphatestonly.cso", wiResourceManager::PIXELSHADER));
|
|
ps[SHADERTYPE_DEFERRED] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassPS_deferred.cso", wiResourceManager::PIXELSHADER));
|
|
ps[SHADERTYPE_FORWARD] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassPS_forward_dirlight.cso", wiResourceManager::PIXELSHADER));
|
|
ps[SHADERTYPE_TILEDFORWARD] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassPS_tiledforward.cso", wiResourceManager::PIXELSHADER));
|
|
|
|
qps[SHADERTYPE_DEPTHONLY] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassPS_alphatestonly.cso", wiResourceManager::PIXELSHADER));
|
|
qps[SHADERTYPE_DEFERRED] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassPS_deferred.cso", wiResourceManager::PIXELSHADER));
|
|
qps[SHADERTYPE_FORWARD] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassPS_forward_dirlight.cso", wiResourceManager::PIXELSHADER));
|
|
qps[SHADERTYPE_TILEDFORWARD] = static_cast<PixelShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassPS_tiledforward.cso", wiResourceManager::PIXELSHADER));
|
|
|
|
gs = static_cast<GeometryShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassGS.cso", wiResourceManager::GEOMETRYSHADER));
|
|
qgs = static_cast<GeometryShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qgrassGS.cso", wiResourceManager::GEOMETRYSHADER));
|
|
|
|
cs_RESET = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassCulling_RESETCS.cso", wiResourceManager::COMPUTESHADER));
|
|
cs_CULLING = static_cast<ComputeShader*>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassCullingCS.cso", wiResourceManager::COMPUTESHADER));
|
|
|
|
}
|
|
void wiHairParticle::SetUpStatic()
|
|
{
|
|
Settings(10,25,120);
|
|
|
|
LoadShaders();
|
|
|
|
|
|
RasterizerStateDesc rsd;
|
|
rsd.FillMode=FILL_SOLID;
|
|
rsd.CullMode=CULL_BACK;
|
|
rsd.FrontCounterClockwise=true;
|
|
rsd.DepthBias=0;
|
|
rsd.DepthBiasClamp=0;
|
|
rsd.SlopeScaledDepthBias=0;
|
|
rsd.DepthClipEnable=true;
|
|
rsd.ScissorEnable=false;
|
|
rsd.MultisampleEnable=false;
|
|
rsd.AntialiasedLineEnable=false;
|
|
rs = new RasterizerState;
|
|
wiRenderer::GetDevice()->CreateRasterizerState(&rsd,rs);
|
|
|
|
rsd.FillMode=FILL_SOLID;
|
|
rsd.CullMode=CULL_NONE;
|
|
rsd.FrontCounterClockwise=true;
|
|
rsd.DepthBias=0;
|
|
rsd.DepthBiasClamp=0;
|
|
rsd.SlopeScaledDepthBias=0;
|
|
rsd.DepthClipEnable=true;
|
|
rsd.ScissorEnable=false;
|
|
rsd.MultisampleEnable=false;
|
|
rsd.AntialiasedLineEnable=false;
|
|
ncrs = new RasterizerState;
|
|
wiRenderer::GetDevice()->CreateRasterizerState(&rsd,ncrs);
|
|
|
|
|
|
DepthStencilStateDesc dsd;
|
|
dsd.DepthEnable = true;
|
|
dsd.DepthWriteMask = DEPTH_WRITE_MASK_ALL;
|
|
dsd.DepthFunc = COMPARISON_LESS;
|
|
|
|
dsd.StencilEnable = true;
|
|
dsd.StencilReadMask = 0xFF;
|
|
dsd.StencilWriteMask = 0xFF;
|
|
dsd.FrontFace.StencilFunc = COMPARISON_ALWAYS;
|
|
dsd.FrontFace.StencilPassOp = STENCIL_OP_REPLACE;
|
|
dsd.FrontFace.StencilFailOp = STENCIL_OP_KEEP;
|
|
dsd.FrontFace.StencilDepthFailOp = STENCIL_OP_KEEP;
|
|
dsd.BackFace.StencilFunc = COMPARISON_ALWAYS;
|
|
dsd.BackFace.StencilPassOp = STENCIL_OP_REPLACE;
|
|
dsd.BackFace.StencilFailOp = STENCIL_OP_KEEP;
|
|
dsd.BackFace.StencilDepthFailOp = STENCIL_OP_KEEP;
|
|
// Create the depth stencil state.
|
|
dss = new DepthStencilState;
|
|
wiRenderer::GetDevice()->CreateDepthStencilState(&dsd, dss);
|
|
|
|
|
|
BlendStateDesc bld;
|
|
ZeroMemory(&bld, sizeof(bld));
|
|
bld.RenderTarget[0].BlendEnable=false;
|
|
bld.RenderTarget[0].SrcBlend = BLEND_SRC_ALPHA;
|
|
bld.RenderTarget[0].DestBlend = BLEND_INV_SRC_ALPHA;
|
|
bld.RenderTarget[0].BlendOp = BLEND_OP_ADD;
|
|
bld.RenderTarget[0].SrcBlendAlpha = BLEND_ONE;
|
|
bld.RenderTarget[0].DestBlendAlpha = BLEND_ONE;
|
|
bld.RenderTarget[0].BlendOpAlpha = BLEND_OP_MAX;
|
|
bld.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL;
|
|
bld.AlphaToCoverageEnable=false; // maybe for msaa
|
|
bs = new BlendState;
|
|
wiRenderer::GetDevice()->CreateBlendState(&bld,bs);
|
|
}
|
|
void wiHairParticle::Settings(int l0,int l1,int l2)
|
|
{
|
|
LOD[0]=l0;
|
|
LOD[1]=l1;
|
|
LOD[2]=l2;
|
|
}
|
|
|
|
|
|
void wiHairParticle::Generate()
|
|
{
|
|
points.clear();
|
|
|
|
Mesh* mesh = object->mesh;
|
|
|
|
XMMATRIX matr = object->getMatrix();
|
|
|
|
int dVG = -1, lVG = -1;
|
|
if (densityG.compare("")) {
|
|
for (unsigned int i = 0; i < mesh->vertexGroups.size(); ++i)
|
|
if (!mesh->vertexGroups[i].name.compare(densityG))
|
|
dVG = i;
|
|
}
|
|
if (lenG.compare("")) {
|
|
for (unsigned int i = 0; i < mesh->vertexGroups.size(); ++i)
|
|
if (!mesh->vertexGroups[i].name.compare(lenG))
|
|
lVG = i;
|
|
}
|
|
|
|
float avgPatchSize;
|
|
if(dVG>=0)
|
|
avgPatchSize = (float)count/((float)mesh->vertexGroups[dVG].vertices.size()/3.0f);
|
|
else
|
|
avgPatchSize = (float)count/((float)mesh->indices.size()/3.0f);
|
|
|
|
if (mesh->indices.size() < 4)
|
|
return;
|
|
|
|
for (unsigned int i = 0; i<mesh->indices.size() - 3; i += 3)
|
|
{
|
|
|
|
unsigned int vi[]={mesh->indices[i],mesh->indices[i+1],mesh->indices[i+2]};
|
|
float denMod[]={1,1,1},lenMod[]={1,1,1};
|
|
if (dVG >= 0) {
|
|
auto found = mesh->vertexGroups[dVG].vertices.find(vi[0]);
|
|
if (found != mesh->vertexGroups[dVG].vertices.end())
|
|
denMod[0] = found->second;
|
|
else
|
|
continue;
|
|
|
|
found = mesh->vertexGroups[dVG].vertices.find(vi[1]);
|
|
if (found != mesh->vertexGroups[dVG].vertices.end())
|
|
denMod[1] = found->second;
|
|
else
|
|
continue;
|
|
|
|
found = mesh->vertexGroups[dVG].vertices.find(vi[2]);
|
|
if (found != mesh->vertexGroups[dVG].vertices.end())
|
|
denMod[2] = found->second;
|
|
else
|
|
continue;
|
|
}
|
|
if (lVG >= 0) {
|
|
auto found = mesh->vertexGroups[lVG].vertices.find(vi[0]);
|
|
if (found != mesh->vertexGroups[lVG].vertices.end())
|
|
lenMod[0] = found->second;
|
|
else
|
|
continue;
|
|
|
|
found = mesh->vertexGroups[lVG].vertices.find(vi[1]);
|
|
if (found != mesh->vertexGroups[lVG].vertices.end())
|
|
lenMod[1] = found->second;
|
|
else
|
|
continue;
|
|
|
|
found = mesh->vertexGroups[lVG].vertices.find(vi[2]);
|
|
if (found != mesh->vertexGroups[lVG].vertices.end())
|
|
lenMod[2] = found->second;
|
|
else
|
|
continue;
|
|
}
|
|
for (int m = 0; m < 3; ++m) {
|
|
if (denMod[m] < 0) denMod[m] = 0;
|
|
if (lenMod[m] < 0) lenMod[m] = 0;
|
|
}
|
|
|
|
Vertex verts[3];
|
|
verts[0].pos = mesh->vertices[VPROP_POS][vi[0]];
|
|
verts[0].nor = mesh->vertices[VPROP_NOR][vi[0]];
|
|
verts[1].pos = mesh->vertices[VPROP_POS][vi[1]];
|
|
verts[1].nor = mesh->vertices[VPROP_NOR][vi[1]];
|
|
verts[2].pos = mesh->vertices[VPROP_POS][vi[2]];
|
|
verts[2].nor = mesh->vertices[VPROP_NOR][vi[2]];
|
|
|
|
if(
|
|
(denMod[0]>FLT_EPSILON || denMod[1]>FLT_EPSILON || denMod[2]>FLT_EPSILON) &&
|
|
(lenMod[0]>FLT_EPSILON || lenMod[1]>FLT_EPSILON || lenMod[2]>FLT_EPSILON)
|
|
)
|
|
{
|
|
|
|
float density = (float)(denMod[0]+denMod[1]+denMod[2])/3.0f*avgPatchSize;
|
|
int rdense = (int)(( density - (int)density ) * 100);
|
|
density += ((wiRandom::getRandom(0, 99)) <= rdense ? 1.0f : 0.0f);
|
|
int PATCHSIZE = material->texture?(int)density:(int)density*10;
|
|
|
|
if(PATCHSIZE)
|
|
{
|
|
|
|
for(int p=0;p<PATCHSIZE;++p)
|
|
{
|
|
float f = wiRandom::getRandom(0, 1000) * 0.001f, g = wiRandom::getRandom(0, 1000) * 0.001f;
|
|
if (f + g > 1)
|
|
{
|
|
f = 1 - f;
|
|
g = 1 - g;
|
|
}
|
|
XMVECTOR pos[] = {
|
|
XMVector3Transform(XMLoadFloat4(&verts[0].pos),matr)
|
|
, XMVector3Transform(XMLoadFloat4(&verts[1].pos),matr)
|
|
, XMVector3Transform(XMLoadFloat4(&verts[2].pos),matr)
|
|
};
|
|
XMVECTOR vbar=XMVectorBaryCentric(
|
|
pos[0],pos[1],pos[2]
|
|
, f
|
|
, g
|
|
);
|
|
XMVECTOR nbar=XMVectorBaryCentric(
|
|
XMLoadFloat4(&verts[0].nor)
|
|
, XMLoadFloat4(&verts[1].nor)
|
|
, XMLoadFloat4(&verts[2].nor)
|
|
, f
|
|
, g
|
|
);
|
|
int ti = wiRandom::getRandom(0, 2);
|
|
XMVECTOR tangent = XMVector3Normalize( XMVectorSubtract(pos[ti],pos[(ti+1)%3]) );
|
|
|
|
Point addP;
|
|
::XMStoreFloat4(&addP.posRand,vbar);
|
|
::XMStoreFloat4(&addP.normalLen,XMVector3Normalize(nbar));
|
|
::XMStoreFloat4(&addP.tangent,tangent);
|
|
|
|
float lbar = lenMod[0] + f*(lenMod[1]-lenMod[0]) + g*(lenMod[2]-lenMod[0]);
|
|
addP.normalLen.w = length*lbar + (float)(wiRandom::getRandom(0, 1000) - 500)*0.001f*length*lbar;
|
|
addP.posRand.w = (float)wiRandom::getRandom(0, 1000);
|
|
points.push_back(addP);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
SAFE_DELETE(cb);
|
|
SAFE_DELETE(vb);
|
|
SAFE_DELETE(ib);
|
|
|
|
GPUBufferDesc bd;
|
|
ZeroMemory(&bd, sizeof(bd));
|
|
bd.Usage = USAGE_IMMUTABLE;
|
|
bd.ByteWidth = (UINT)(sizeof(Point) * points.size());
|
|
bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE;
|
|
bd.CPUAccessFlags = 0;
|
|
bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
|
|
SubresourceData data = {};
|
|
data.pSysMem = points.data();
|
|
vb = new GPUBuffer;
|
|
wiRenderer::GetDevice()->CreateBuffer(&bd, &data, vb);
|
|
|
|
|
|
//uint32_t* indices = new uint32_t[points.size()];
|
|
//for (size_t i = 0; i < points.size(); ++i)
|
|
//{
|
|
// indices[i] = (uint32_t)i;
|
|
//}
|
|
//data.pSysMem = indices;
|
|
|
|
bd.Usage = USAGE_DEFAULT;
|
|
bd.ByteWidth = (UINT)(sizeof(uint32_t) * points.size());
|
|
bd.BindFlags = BIND_INDEX_BUFFER | BIND_UNORDERED_ACCESS;
|
|
bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
|
|
ib = new GPUBuffer;
|
|
wiRenderer::GetDevice()->CreateBuffer(&bd, /*&data*/nullptr, ib);
|
|
|
|
|
|
//IndirectDrawArgsIndexedInstanced args;
|
|
//args.BaseVertexLocation = 0;
|
|
//args.IndexCountPerInstance = (UINT)points.size();
|
|
//args.InstanceCount = 1;
|
|
//args.StartIndexLocation = 0;
|
|
//args.StartInstanceLocation = 0;
|
|
//data.pSysMem = &args;
|
|
|
|
bd.ByteWidth = (UINT)(sizeof(IndirectDrawArgsIndexedInstanced));
|
|
bd.MiscFlags = RESOURCE_MISC_DRAWINDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
|
|
bd.BindFlags = BIND_UNORDERED_ACCESS;
|
|
drawargs = new GPUBuffer;
|
|
wiRenderer::GetDevice()->CreateBuffer(&bd, /*&data*/nullptr, drawargs);
|
|
|
|
|
|
|
|
|
|
ZeroMemory(&bd, sizeof(bd));
|
|
bd.Usage = USAGE_DYNAMIC;
|
|
bd.ByteWidth = sizeof(ConstantBuffer);
|
|
bd.BindFlags = BIND_CONSTANT_BUFFER;
|
|
bd.CPUAccessFlags = CPU_ACCESS_WRITE;
|
|
cb = new GPUBuffer;
|
|
wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, cb);
|
|
|
|
}
|
|
|
|
void wiHairParticle::ComputeCulling(Camera* camera, GRAPHICSTHREAD threadID)
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
device->EventBegin("HairParticle - Culling", threadID);
|
|
|
|
XMMATRIX inverseMat = XMLoadFloat4x4(&OriginalMatrix_Inverse);
|
|
XMMATRIX renderMatrix = inverseMat * object->getMatrix();
|
|
|
|
ConstantBuffer gcb;
|
|
gcb.mWorld = XMMatrixTranspose(renderMatrix);
|
|
gcb.color = material->baseColor;
|
|
gcb.LOD0 = (float)LOD[0];
|
|
gcb.LOD1 = (float)LOD[1];
|
|
gcb.LOD2 = (float)LOD[2];
|
|
|
|
device->UpdateBuffer(cb, &gcb, threadID);
|
|
device->BindConstantBufferCS(cb, CB_GETBINDSLOT(ConstantBuffer), threadID);
|
|
|
|
device->BindResourceCS(vb, 0, threadID);
|
|
|
|
const GPUUnorderedResource* uavs[] = {
|
|
static_cast<const GPUUnorderedResource*>(drawargs),
|
|
static_cast<const GPUUnorderedResource*>(ib),
|
|
};
|
|
device->BindUnorderedAccessResourcesCS(uavs, 0, ARRAYSIZE(uavs), threadID);
|
|
|
|
// First clear the drawarg buffer:
|
|
device->BindCS(cs_RESET, threadID);
|
|
device->Dispatch(1, 1, 1, threadID);
|
|
|
|
// Then compute culling:
|
|
device->BindCS(cs_CULLING, threadID);
|
|
device->Dispatch((UINT)ceilf((float)points.size() / GRASS_CULLING_THREADCOUNT), 1, 1, threadID);
|
|
|
|
// Then reset state:
|
|
device->BindCS(nullptr, threadID);
|
|
device->UnBindUnorderedAccessResources(0, ARRAYSIZE(uavs), threadID);
|
|
device->UnBindResources(0, 1, threadID);
|
|
|
|
device->EventEnd(threadID);
|
|
}
|
|
|
|
void wiHairParticle::Draw(Camera* camera, SHADERTYPE shaderType, GRAPHICSTHREAD threadID)
|
|
{
|
|
Texture2D* texture = material->texture;
|
|
PixelShader* _ps = texture != nullptr ? qps[shaderType] : ps[shaderType];
|
|
if (_ps == nullptr)
|
|
return;
|
|
|
|
{
|
|
GraphicsDevice* device = wiRenderer::GetDevice();
|
|
device->EventBegin("HairParticle - Draw", threadID);
|
|
|
|
|
|
device->BindPrimitiveTopology(PRIMITIVETOPOLOGY::POINTLIST,threadID);
|
|
device->BindVertexLayout(il,threadID);
|
|
device->BindPS(_ps,threadID);
|
|
device->BindVS(vs,threadID);
|
|
|
|
if(texture)
|
|
{
|
|
device->BindResourcePS(texture,TEXSLOT_ONDEMAND0,threadID);
|
|
device->BindResourceGS(texture,TEXSLOT_ONDEMAND0,threadID);
|
|
}
|
|
|
|
device->BindRasterizerState(ncrs, threadID);
|
|
|
|
device->BindConstantBufferGS(cb, CB_GETBINDSLOT(ConstantBuffer),threadID);
|
|
|
|
if (texture)
|
|
{
|
|
device->BindGS(qgs, threadID);
|
|
}
|
|
else
|
|
{
|
|
device->BindGS(gs, threadID);
|
|
}
|
|
|
|
const GPUBuffer* vbs[] = {
|
|
vb,
|
|
};
|
|
const UINT strides[] = {
|
|
sizeof(Point),
|
|
};
|
|
device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, threadID);
|
|
device->BindIndexBuffer(ib, INDEXBUFFER_FORMAT::INDEXFORMAT_32BIT, threadID);
|
|
|
|
device->DrawIndexedInstancedIndirect(drawargs, 0, threadID);
|
|
|
|
device->BindGS(nullptr,threadID);
|
|
|
|
device->EventEnd(threadID);
|
|
}
|
|
}
|
|
|
|
|
|
void wiHairParticle::Serialize(wiArchive& archive)
|
|
{
|
|
if (archive.IsReadMode())
|
|
{
|
|
archive >> length;
|
|
archive >> count;
|
|
archive >> name;
|
|
archive >> densityG;
|
|
archive >> lenG;
|
|
archive >> materialName;
|
|
archive >> OriginalMatrix_Inverse;
|
|
}
|
|
else
|
|
{
|
|
archive << length;
|
|
archive << count;
|
|
archive << name;
|
|
archive << densityG;
|
|
archive << lenG;
|
|
archive << materialName;
|
|
archive << OriginalMatrix_Inverse;
|
|
}
|
|
}
|