Files
WickedEngine/WickedEngine/wiHairParticle.cpp
T
turanszkij 468993f5dd refactor
2016-01-09 21:18:31 +01:00

546 lines
18 KiB
C++

#include "wiHairParticle.h"
#include "wiRenderer.h"
#include "wiResourceManager.h"
#include "wiLoader.h"
#include "wiMath.h"
#include "wiFrustum.h"
#include "wiRandom.h"
VertexLayout wiHairParticle::il;
VertexShader wiHairParticle::vs;
PixelShader wiHairParticle::ps,wiHairParticle::qps;
GeometryShader wiHairParticle::gs[],wiHairParticle::qgs[];
BufferResource wiHairParticle::cbgs;
DepthStencilState wiHairParticle::dss;
RasterizerState wiHairParticle::rs, wiHairParticle::ncrs;
Sampler wiHairParticle::ss;
BlendState wiHairParticle::bs;
int wiHairParticle::LOD[3];
wiHairParticle::wiHairParticle()
{
}
wiHairParticle::wiHairParticle(const string& newName, float newLen, int newCount
, const string& newMat, Object* newObject, const string& densityGroup, const string& lengthGroup)
{
name=newName;
densityG=densityGroup;
lenG=lengthGroup;
length=newLen;
count=newCount;
material=nullptr;
object = newObject;
for(Material* m : object->mesh->materials)
if(!newMat.compare(m->name)){
material = m;
break;
}
if(material)
SetUpPatches();
}
void wiHairParticle::CleanUp(){
for (unsigned int i = 0; i<patches.size(); ++i)
patches[i]->CleanUp();
patches.clear();
wiRenderer::SafeRelease(vb[0]);
wiRenderer::SafeRelease(vb[1]);
wiRenderer::SafeRelease(vb[2]);
}
void wiHairParticle::CleanUpStatic(){
if(il) il->Release(); il=NULL;
if(vs) vs->Release(); vs=NULL;
for(int i=0;i<3;++i){
if(gs[i]) gs[i]->Release(); gs[i]=NULL;}
for(int i=0;i<2;++i){
if(qgs[i]) qgs[i]->Release(); qgs[i]=NULL;}
if(ps) ps->Release(); ps=NULL;
if(qps) qps->Release(); qps=NULL;
if(cbgs) cbgs->Release(); cbgs=NULL;
if(ss) ss->Release(); ss=NULL;
if(bs) bs->Release(); bs=NULL;
if(rs) rs->Release(); rs=NULL;
if(ncrs) ncrs->Release(); ncrs=NULL;
}
void wiHairParticle::LoadShaders()
{
VertexLayoutDesc layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_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;
}
ps = static_cast<PixelShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassPS.cso", wiResourceManager::PIXELSHADER));
qps = static_cast<PixelShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassPS.cso", wiResourceManager::PIXELSHADER));
gs[0] = static_cast<GeometryShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassL0GS.cso", wiResourceManager::GEOMETRYSHADER));
gs[1] = static_cast<GeometryShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassL1GS.cso", wiResourceManager::GEOMETRYSHADER));
gs[2] = static_cast<GeometryShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "grassL2GS.cso", wiResourceManager::GEOMETRYSHADER));
qgs[0] = static_cast<GeometryShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassLCloseGS.cso", wiResourceManager::GEOMETRYSHADER));
qgs[1] = static_cast<GeometryShader>(wiResourceManager::GetShaderManager()->add(wiRenderer::SHADERPATH + "qGrassLDistGS.cso", wiResourceManager::GEOMETRYSHADER));
}
void wiHairParticle::SetUpStatic(){
Settings(10,25,120);
LoadShaders();
//
// ID3DBlob* pVSBlob = NULL;
//if(FAILED(D3DReadFileToBlob(L"shaders/grassVS.cso", &pVSBlob))){MessageBox(0,L"Failed To load grassVS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &vs );
// // Define the input layout
// VertexLayoutDesc layout[] =
// {
// { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
// { "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
// { "TANGENT", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 },
// };
//UINT numElements = ARRAYSIZE( layout );
//
// // Create the input layout
//wiRenderer::graphicsDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
// pVSBlob->GetBufferSize(), &il );
//if(pVSBlob){ pVSBlob->Release();pVSBlob=NULL; }
//
//ID3DBlob* pPSBlob = NULL;
//
//if(FAILED(D3DReadFileToBlob(L"shaders/grassPS.cso", &pPSBlob))){MessageBox(0,L"Failed To load grassPS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &ps );
//if(pPSBlob){ pPSBlob->Release();pPSBlob=NULL; }
//
//if(FAILED(D3DReadFileToBlob(L"shaders/qGrassPS.cso", &pPSBlob))){MessageBox(0,L"Failed To load qGrassPS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &qps );
//if(pPSBlob){ pPSBlob->Release();pPSBlob=NULL; }
//ID3DBlob* pGSBlob = NULL;
//
//if(FAILED(D3DReadFileToBlob(L"shaders/grassL0GS.cso", &pGSBlob))){MessageBox(0,L"Failed To load grassL0GS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &gs[0] );
//if(pGSBlob){ pGSBlob->Release();pGSBlob=NULL; }
//
//if(FAILED(D3DReadFileToBlob(L"shaders/grassL1GS.cso", &pGSBlob))){MessageBox(0,L"Failed To load grassL1GS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &gs[1] );
//if(pGSBlob){ pGSBlob->Release();pGSBlob=NULL; }
//
//if(FAILED(D3DReadFileToBlob(L"shaders/grassL2GS.cso", &pGSBlob))){MessageBox(0,L"Failed To load grassL2GS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &gs[2] );
//if(pGSBlob){ pGSBlob->Release();pGSBlob=NULL; }
//
//
//if(FAILED(D3DReadFileToBlob(L"shaders/qGrassLCloseGS.cso", &pGSBlob))){MessageBox(0,L"Failed To load qGrassLCloseGS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &qgs[0] );
//if(pGSBlob){ pGSBlob->Release();pGSBlob=NULL; }
//
//if(FAILED(D3DReadFileToBlob(L"shaders/qGrassLDistGS.cso", &pGSBlob))){MessageBox(0,L"Failed To load qGrassLDistGS.cso",0,0);}
//else wiRenderer::graphicsDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &qgs[1] );
//if(pGSBlob){ pGSBlob->Release();pGSBlob=NULL; }
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(CBGS);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
wiRenderer::graphicsDevice->CreateBuffer( &bd, NULL, &cbgs );
D3D11_RASTERIZER_DESC rsd;
rsd.FillMode=D3D11_FILL_SOLID;
rsd.CullMode=D3D11_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;
wiRenderer::graphicsDevice->CreateRasterizerState(&rsd,&rs);
rsd.FillMode=D3D11_FILL_SOLID;
rsd.CullMode=D3D11_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;
wiRenderer::graphicsDevice->CreateRasterizerState(&rsd,&ncrs);
D3D11_DEPTH_STENCIL_DESC dsd;
dsd.DepthEnable = true;
dsd.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
dsd.DepthFunc = D3D11_COMPARISON_LESS;
dsd.StencilEnable = true;
dsd.StencilReadMask = 0xFF;
dsd.StencilWriteMask = 0xFF;
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
// Create the depth stencil state.
wiRenderer::graphicsDevice->CreateDepthStencilState(&dsd, &dss);
D3D11_SAMPLER_DESC samplerDesc;
samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 16;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
wiRenderer::graphicsDevice->CreateSamplerState(&samplerDesc, &ss);
D3D11_BLEND_DESC bld;
ZeroMemory(&bld, sizeof(bld));
bld.RenderTarget[0].BlendEnable=false;
bld.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bld.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bld.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bld.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bld.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bld.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
bld.RenderTarget[0].RenderTargetWriteMask = 0x0f;
bld.AlphaToCoverageEnable=false;
wiRenderer::graphicsDevice->CreateBlendState(&bld,&bs);
}
void wiHairParticle::Settings(int l0,int l1,int l2)
{
LOD[0]=l0;
LOD[1]=l1;
LOD[2]=l2;
}
struct PatchHolder:public Cullable
{
wiHairParticle::Patch* patch;
PatchHolder(){}
PatchHolder(wiHairParticle::Patch* p){patch=p;}
};
void wiHairParticle::SetUpPatches()
{
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(Point)*MAX_PARTICLES;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
wiRenderer::graphicsDevice->CreateBuffer( &bd, NULL, &vb[0] );
wiRenderer::graphicsDevice->CreateBuffer( &bd, NULL, &vb[1] );
wiRenderer::graphicsDevice->CreateBuffer( &bd, NULL, &vb[2] );
const int triangleperpatch = 4;
int currentTris=0;
vector<PatchHolder*> pholder;
patches.push_back(new Patch());
pholder.push_back(new PatchHolder(patches.back()));
Mesh* mesh = object->mesh;
XMMATRIX matr = XMLoadFloat4x4(&object->world);
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;
}
SkinnedVertex* v[] = {
&mesh->vertices[vi[0]],
&mesh->vertices[vi[1]],
&mesh->vertices[vi[2]],
};
if(
(denMod[0] || denMod[1] || denMod[2]) &&
(lenMod[0] || lenMod[1] || lenMod[2])
)
{
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;
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(&v[0]->pos),matr)
, XMVector3Transform(XMLoadFloat4(&v[1]->pos),matr)
, XMVector3Transform(XMLoadFloat4(&v[2]->pos),matr)
};
XMVECTOR vbar=XMVectorBaryCentric(
pos[0],pos[1],pos[2]
, f
, g
);
XMVECTOR nbar=XMVectorBaryCentric(
XMLoadFloat4(&v[0]->nor)
, XMLoadFloat4(&v[1]->nor)
, XMLoadFloat4(&v[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);
patches.back()->add(addP);
XMFLOAT3 posN = XMFLOAT3(addP.posRand.x,addP.posRand.y,addP.posRand.z);
patches.back()->min=wiMath::Min(patches.back()->min,posN);
patches.back()->max=wiMath::Max(patches.back()->max,posN);
}
/*patches.back()->max.y+=length;
patches.back()->max.x+=length*0.5f;
patches.back()->max.z+=length*0.5f;
patches.back()->min.x-=length*0.5f;
patches.back()->min.z-=length*0.5f;*/
if(currentTris>=triangleperpatch){
pholder.back()->bounds.create(patches.back()->min,patches.back()->max);
currentTris=0;
//D3D11_BUFFER_DESC bd;
//ZeroMemory( &bd, sizeof(bd) );
//bd.Usage = D3D11_USAGE_IMMUTABLE;
//bd.ByteWidth = sizeof( Point ) * patches.back()->p.size();
//bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
//bd.CPUAccessFlags = 0;
//D3D11_SUBRESOURCE_DATA InitData;
//ZeroMemory( &InitData, sizeof(InitData) );
//InitData.pSysMem = patches.back()->p.data();
//wiRenderer::graphicsDevice->CreateBuffer( &bd, &InitData, &patches.back()->vb );
patches.push_back(new Patch());
pholder.push_back(new PatchHolder(patches.back()));
}
else
currentTris++;
}
}
}
GenerateSPTree(spTree,vector<Cullable*>(pholder.begin(),pholder.end()),SPTREE_GENERATE_OCTREE);
return;
}
void wiHairParticle::Draw(Camera* camera, ID3D11DeviceContext *context)
{
static thread_local Frustum frustum = Frustum();
frustum.ConstructFrustum((float)LOD[2], camera->Projection, camera->View);
CulledList culledPatches;
if(spTree)
wiSPTree::getVisible(spTree->root,frustum,culledPatches,SP_TREE_STRICT_CULL);
if(!culledPatches.empty())
{
TextureView texture = material->texture;
wiRenderer::BindPrimitiveTopology(PRIMITIVETOPOLOGY::POINTLIST,context);
wiRenderer::BindVertexLayout(il,context);
wiRenderer::BindPS(texture?qps:ps,context);
wiRenderer::BindVS(vs,context);
if(texture){
wiRenderer::BindTexturePS(texture,0,context);
wiRenderer::BindSamplerPS(ss,0,context);
wiRenderer::BindTextureGS(texture,0,context);
wiRenderer::BindBlendState(bs,context);
}
else
wiRenderer::BindRasterizerState(ncrs,context);
static thread_local CBGS* gcb = new CBGS;
(*gcb).mView = XMMatrixTranspose(camera->GetView());
(*gcb).mProj = XMMatrixTranspose(camera->GetProjection());
(*gcb).mPrevViewProjection = XMMatrixTranspose(wiRenderer::prevFrameCam->GetViewProjection());
(*gcb).colTime=XMFLOAT4(material->diffuseColor.x,material->diffuseColor.y,material->diffuseColor.z,wiRenderer::wind.time);
(*gcb).eye=camera->translation;
(*gcb).drawdistance = (float)LOD[2];
(*gcb).wind=wiRenderer::wind.direction;
(*gcb).windRandomness=wiRenderer::wind.randomness;
(*gcb).windWaveSize=wiRenderer::wind.waveSize;
wiRenderer::UpdateBuffer(cbgs,gcb,context);
wiRenderer::BindDepthStencilState(dss,STENCILREF_DEFAULT,context);
wiRenderer::BindConstantBufferGS(cbgs,0,context);
for(int i=0;i<3;++i){
vector<Point> renderPoints;
renderPoints.reserve(MAX_PARTICLES);
if(texture){
wiRenderer::BindGS(i<2?qgs[0]:qgs[1],context);
wiRenderer::BindRasterizerState(i<2?ncrs:rs,context);
}
else
wiRenderer::BindGS(gs[i],context);
CulledList::iterator iter = culledPatches.begin();
while(iter != culledPatches.end()){
Cullable* culled = *iter;
Patch* patch = ((PatchHolder*)culled)->patch;
float dis = wiMath::Distance(camera->translation,((PatchHolder*)culled)->bounds.getCenter());
if(dis<LOD[i]){
culledPatches.erase(iter++);
culled=NULL;
renderPoints.insert(renderPoints.end(),patch->p.begin(),patch->p.end());
}
else
++iter;
}
wiRenderer::UpdateBuffer(vb[i],renderPoints.data(),context,sizeof(Point)*renderPoints.size());
wiRenderer::BindVertexBuffer(vb[i],0,sizeof(Point),context);
wiRenderer::Draw(renderPoints.size(),context);
}
wiRenderer::BindGS(nullptr,context);
wiRenderer::BindConstantBufferGS(nullptr,0,context);
}
}
wiHairParticle::Patch::Patch(){
p.resize(0);
min=XMFLOAT3(D3D11_FLOAT32_MAX,D3D11_FLOAT32_MAX,D3D11_FLOAT32_MAX);
max=XMFLOAT3(-D3D11_FLOAT32_MAX,-D3D11_FLOAT32_MAX,-D3D11_FLOAT32_MAX);
//vb=NULL;
}
void wiHairParticle::Patch::add(const Point& pp){
p.push_back(pp);
}
void wiHairParticle::Patch::CleanUp(){
p.clear();
//if(vb)
// vb->Release();
//vb=NULL;
}