610 likes | 750 Views
GraphGame gg0 1 1-Particles. Plakátok, részecskerendszerek Szécsi László. gg0 1 1-Particles project. copy-paste-rename gg00 9 - Gui folder (sok zsiráf nem kell ide) vcxproj , filters átnevezés solution /add existing project rename project working dir: $( SolutionDir )
E N D
GraphGamegg011-Particles Plakátok, részecskerendszerek SzécsiLászló
gg011-Particles project • copy-paste-rename gg009-Guifolder (sok zsiráf nem kell ide) • vcxproj, filters átnevezés • solution/add existing project • rename project • working dir: $(SolutionDir) • Project Properties/ConfigurationProperties/Debugging/CommandArguments --solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)" • build, run
Particle osztály #include "Math/math.h" classParticle { friend class Game; Egg::Math::float3 position; Egg::Math::float3 velocity; float lifespan; float age; public: };
Particle osztály void reborn() { using namespace Egg::Math; position = float3::random(-1,1); velocity = position * 5; age = 0; lifespan = float1::random(2,5); } Particle(){ reborn(); }
Particle buffer, input layout és pass • Lehetne ezeket kézzel létrehozni • ugyanúgy, ahogy a háromszögrajzolásnál az elején • csak a shader az effectfileból jön • D3DX11_PASS_DESC billboardPassDesc; • effect->GetTechniqueByName("billboard")->GetPassByName("fire")->GetDesc(&billboardPassDesc); • és a VB használati módja dinamikus • rajzoláskor • context->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); • effect->GetTechniqueByName("billboard")->GetPassByName("fire")->Apply(0, context); • context->Draw(particles.size(), 0);
Egg::Mesh-t használva • Mesh::VertexStream a buffer • Effect pass-ra Mesh::Material • InputLayoutgyártása a Mesh::Binder feladata • a végén kapunk egy Mesh::Shaded-et amit csak ki kell rajzolni • beállítja az effectpass-t • az input layoutot • a vertexbuffert • rajzol
Game.h #include "Particle.h" #include <vector>
Game.h class Game : public Egg::Sas::SasApp { std::vector<Particle> particles; Egg::Mesh::Shaded::P fireBillboardSet;
createResources for(inti=0; i<40; i++) particles.push_back(Particle());
createResources D3D11_INPUT_ELEMENT_DESC particleElements[3]; particleElements[0].AlignedByteOffset = offsetof(Particle, position); particleElements[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; particleElements[0].InputSlot = 0; particleElements[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; particleElements[0].InstanceDataStepRate = 0; particleElements[0].SemanticIndex = 0; particleElements[0].SemanticName = "POSITION"; particleElements[1].AlignedByteOffset = offsetof(Particle, lifespan); particleElements[1].Format = DXGI_FORMAT_R32_FLOAT; particleElements[1].InputSlot = 0; particleElements[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; particleElements[1].InstanceDataStepRate = 0; particleElements[1].SemanticIndex = 0; particleElements[1].SemanticName = "LIFESPAN"; particleElements[2].AlignedByteOffset = offsetof(Particle, age); particleElements[2].Format = DXGI_FORMAT_R32_FLOAT; particleElements[2].InputSlot = 0; particleElements[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; particleElements[2].InstanceDataStepRate = 0; particleElements[2].SemanticIndex = 0; particleElements[2].SemanticName = "AGE";
createResources Egg::Mesh::VertexStreamDescparticleBufferDesc; particleBufferDesc.elements = particleElements; particleBufferDesc.nElements = 3; particleBufferDesc.nVertices = particles.size(); particleBufferDesc.vertexStride = sizeof(Particle); particleBufferDesc.vertexData = &particles.at(0); particleBufferDesc.cpuAccessFlags = D3D11_CPU_ACCESS_WRITE; particleBufferDesc.usage = D3D11_USAGE_DYNAMIC;
createResources Egg::Mesh::VertexStream::P particleVertexStream = Egg::Mesh::VertexStream::create( device, particleBufferDesc);
createResources ID3DX11EffectPass* billboardPass = effect-> GetTechniqueByName("billboard")-> GetPassByName("fire"); Egg::Mesh::Material::P fireMaterial =Egg::Mesh::Material::create( billboardPass, 0); fireBillboardSet = binder->bindMaterial( fireMaterial, particleVertexStream);
releaseResources fireBillboardSet.reset();
render fireBillboardSet->draw(context);
Új fx file • solutionfxfolderbe • billboard.fx
#9.0 fx/main.fx #include <envmapped.fx> #include <billboard.fx>
#9.0 fx/billboard.fx structIaosBillboard { float3 pos : POSITION; float lifespan : LIFESPAN; float age : AGE; }; typedefIaosBillboardVsosBillboard; VsosBillboardvsBillboard(IaosBillboard input) { return input; }
#9.0 fx/billboard.fx structGsosBillboard { float4 pos : SV_Position; float2 tex : TEXCOORD; }; float billboardWidth = 0.1; float billboardHeight = 0.1;
#9.0 fx/billboard.fx [maxvertexcount(4)] void gsBillboard( point VsosBillboard input[1], inoutTriangleStream<GsosBillboard> stream){ float4 hndcPos = mul(float4(input[0].pos, 1), modelViewProjMatrix); GsosBillboard output; output.pos = hndcPos; output.pos.x += billboardWidth; output.pos.y += billboardHeight; output.tex = float2(1, 0); stream.Append(output); output.pos = hndcPos; output.pos.x += billboardWidth; output.pos.y -= billboardHeight; output.tex = float2(1, 1); stream.Append(output); output.pos = hndcPos; output.pos.x -= billboardWidth; output.pos.y += billboardHeight; output.tex = float2(0, 0); stream.Append(output); output.pos = hndcPos; output.pos.x -= billboardWidth; output.pos.y -= billboardHeight; output.tex = float2(0, 1); stream.Append(output);}
#9.0 fx/billboard.fx float4 psFire(GsosBillboard input) : SV_Target { return input.tex.xyyy; } technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); } }
Textúra • particle.dds letöltése • Projects/gg011-Particles/Media folderbe
Game class class Game : public Egg::Sas::SasApp { ID3D11ShaderResourceView* billboardSrv;
createResources D3DX11CreateShaderResourceViewFromFileA( device, systemEnvironment.resolveMediaPath( "particle.dds" ).c_str(), NULL, NULL, &billboardSrv, NULL); effect-> GetVariableByName("billboardTexture") ->AsShaderResource(billboardSrv);
releaseResources billboardSrv->Release();
#9.0 fx/billboard.fx Texture2D billboardTexture; float4 psFire(GsosBillboard input) : SV_Target { return billboardTexture.Sample( linearSampler, input.tex.xy); }
createSwapChainResources using namespace Egg::Math; float4 worldBillboardSize(0.2, 0.2, 0, 0); float4 screenBillboardSize = worldBillboardSize * firstPersonCam->getProjMatrix(); effect-> GetVariableByName("billboardWidth")-> AsScalar()-> SetFloat(screenBillboardSize.x); effect-> GetVariableByName("billboardHeight")-> AsScalar()-> SetFloat(screenBillboardSize.y);
Alphablending • BlendState-et kell definiálni, pass-ban kiválasztani • a többi pass-ban viszont vissza kéne állítani • legyen a blendStates.fx, amibe az összes BlendState-et gyűjtjük • legyenakkor már • rasterizerStates.fx • depthStencilStates.fx
#9.0 fx/blendStates.fx BlendStatedefaultBlender { }; BlendStateadditiveBlender { BlendEnable[0] = true; SrcBlend = src_alpha; DestBlend = one; BlendOp = add; SrcBlendAlpha = one; DestBlendAlpha = one; BlendOpAlpha = add; };
#9.0 fx/blendStates.fx RasterizerStatedefaultRasterizer { }; RasterizerStatenoCullRasterizer { CullMode = none; FillMode = solid; }; RasterizerStatebackfaceRasterizer { CullMode = front; FillMode = solid; }; RasterizerStatewireframeRasterizer { CullMode = none; FillMode = wireFrame; };
#9.0 depthStencilStates.fx DepthStencilStatedefaultCompositor { }; DepthStencilStatenoDepthTestCompositor { DepthEnable = false; DepthWriteMask = zero; }; DepthStencilStatenoDepthWriteCompositor { DepthEnable = true; DepthWriteMask = zero; };
#9.0 fx/basic.fx #include <blendStates.fx> #include <rasterizerStates.fx> #include <depthStencilStates.fx> ... technique11 basic { pass basic { SetVertexShader ( CompileShader( vs_5_0, vsTrafo() ) ); SetGeometryShader( NULL ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psBasic() ) ); SetDepthStencilState( defaultCompositor, 0 ); SetBlendState( defaultBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
Minden pass legyen teljes • textured/textured • shaded/diffuse, shaded/specular • envmapped/envmapped, envmapped/background
#9.0 fx/billboard.fx technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); SetDepthStencilState( defaultCompositor, 0 ); SetBlendState( defaultBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
#9.0 fx/billboard.fx technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); SetDepthStencilState( defaultCompositor, 0 ); SetBlendState( additiveBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
#9.0 fx/billboard.fx technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); SetDepthStencilState( noDepthTestCompositor, 0 ); SetBlendState( additiveBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
#9.0 fx/billboard.fx technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); SetDepthStencilState( noDepthWriteCompositor, 0 ); SetBlendState( additiveBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
#9.0 fx/billboard.fx technique11 billboard{ pass fire{ SetVertexShader ( CompileShader( vs_5_0, vsBillboard() ) ); SetGeometryShader ( CompileShader( gs_5_0, gsBillboard() ) ); SetRasterizerState( defaultRasterizer ); SetPixelShader( CompileShader( ps_5_0, psFire() ) ); SetDepthStencilState( noDepthWriteCompositor, 0 ); SetBlendState( transparencyBlender, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF ); } }
Rossz a sorrend… hátsók takarnak előbbiekre Ehhez rendezni kellene a plakátokat mélység szerint… egyelőre inkább vissza az additívhoz!
#9.0 Legyen színesebb float4 psFire(GsosBillboard input) : SV_Target { float4 color = billboardTexture.Sample(linearSampler, input.tex.xy); color.rgb = float3(color.a, pow(color.a, 4), pow(color.a, 10)); return color; }
Nagyobb tűz using namespace Egg::Math; firstPersonCam = Egg::Cam::FirstPerson::create() ->setView( float3(0, 0, 200), float3(0, 0, -1)) ->setProj(1.2, 1, 1, 1000) ->setSpeed(50); float4 worldBillboardSize(50.0, 50.0, 0, 0);
Particle void move(float dt) { position +=velocity * dt; age += dt; if(age > lifespan) reborn(); }