plakátok, részecskerendszerek szécsi lászló. copy-paste-rename gg009-gui folder (sok zsiráf...

Post on 01-Apr-2015

215 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

GraphGamegg011-Particles

Plakátok, részecskerendszerek

Szécsi László

gg011-Particles project

• copy-paste-rename gg009-Gui folder (sok zsiráf nem kell ide)

• vcxproj, filters átnevezés• solution/add existing project• rename project• working dir: $(SolutionDir)• Project Properties/Configuration

Properties/Debugging/Command Arguments--solutionPath:"$(SolutionDir)" --projectPath:"$(ProjectDir)"

• build, run

Particle osztály#include "Math/math.h"class Particle{ friend class Game; Egg::Math::float3 position; Egg::Math::float3 velocity; float lifespan; float age;public:};

Particle osztályvoid 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 effect filebó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• InputLayout gyártása a Mesh::Binder feladata• a végén kapunk egy Mesh::Shaded-et amit

csak ki kell rajzolni– beállítja az effect pass-t– az input layoutot– a vertex buffert– rajzol

Game.h#include "Particle.h"#include <vector>

Game.hclass Game : public Egg::Sas::SasApp

{ std::vector<Particle> particles; Egg::Mesh::Shaded::P fireBillboardSet;

createResourcesfor(int i=0; i<40; i++) particles.push_back(Particle());

createResourcesD3D11_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";

createResourcesEgg::Mesh::VertexStreamDesc particleBufferDesc;

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;

createResourcesEgg::Mesh::VertexStream::P particleVertexStream = Egg::Mesh::VertexStream::create( device, particleBufferDesc);

createResourcesID3DX11EffectPass* billboardPass = effect-> GetTechniqueByName("billboard")-> GetPassByName("fire");Egg::Mesh::Material::P fireMaterial = Egg::Mesh::Material::create( billboardPass, 0);fireBillboardSet = binder->bindMaterial( fireMaterial, particleVertexStream);

releaseResourcesfireBillboardSet.reset();

renderfireBillboardSet->draw(context);

Új fx file

• solution fx folderbe• billboard.fx

fx/main.fx#include <envmapped.fx>#include <billboard.fx>

#9.0

fx/billboard.fxstruct IaosBillboard{ float3 pos : POSITION; float lifespan : LIFESPAN; float age : AGE;};

typedef IaosBillboard VsosBillboard;

VsosBillboard vsBillboard(IaosBillboard input){ return input;}

#9.0

fx/billboard.fxstruct GsosBillboard{ 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], inout TriangleStream<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.fxfloat4 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() ) ); }}

#9.0

Színes plakátok

Textúra

• particle.dds letöltése• Projects/gg011-Particles/Media folderbe

Game classclass Game : public Egg::Sas::SasApp

{

ID3D11ShaderResourceView* billboardSrv;

createResourcesD3DX11CreateShaderResourceViewFromFileA( device, systemEnvironment.resolveMediaPath( "particle.dds" ).c_str(), NULL, NULL, &billboardSrv, NULL);effect-> GetVariableByName("billboardTexture") ->AsShaderResource(billboardSrv);

releaseResourcesbillboardSrv->Release();

fx/billboard.fxTexture2D billboardTexture;

float4 psFire(GsosBillboard input) : SV_Target{ return billboardTexture.Sample( linearSampler, input.tex.xy);}

#9.0

Textúrázott, de viewporthoz torzuló

createSwapChainResourcesusing 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);

Állandó méretű plakátok

Alpha blending

• 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• legyen akkor már– rasterizerStates.fx– depthStencilStates.fx

fx/blendStates.fxBlendState defaultBlender{};

BlendState additiveBlender{BlendEnable[0] = true;SrcBlend = src_alpha;DestBlend = one;BlendOp = add;SrcBlendAlpha = one;DestBlendAlpha = one;BlendOpAlpha = add;

};

#9.0

fx/blendStates.fxRasterizerState defaultRasterizer{};

RasterizerState noCullRasterizer{

CullMode = none;FillMode = solid;

};

RasterizerState backfaceRasterizer{

CullMode = front;FillMode = solid;

};

RasterizerState wireframeRasterizer{

CullMode = none;FillMode = wireFrame;

};

#9.0

depthStencilStates.fxDepthStencilState defaultCompositor{};

DepthStencilState noDepthTestCompositor{

DepthEnable = false;DepthWriteMask = zero;

};

DepthStencilState noDepthWriteCompositor{ 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 ); }

}

#9.0

Minden pass legyen teljes

• textured/textured• shaded/diffuse, shaded/specular• envmapped/envmapped,

envmapped/background

fx/billboard.fxtechnique11 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

Ugyanaz

fx/billboard.fxtechnique11 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

Blending van… de z-teszt is

fx/billboard.fxtechnique11 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

Nem depth test – zsiráf sem takar

fx/billboard.fxtechnique11 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

Zsiráf takar, plakát nem

fx/billboard.fxtechnique11 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 ); }}

#9.0

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!

Legyen színesebbfloat4 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;}

#9.0

worldBillboardSize (1, 1)

Nagyobb tűzusing 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);

Particlevoid move(float dt){ position +=velocity * dt; age += dt; if(age > lifespan) reborn();}

Game::animatefor(int i = 0; i < particles.size(); i++)

particles.at(i).move(dt);

Game::animateID3D11Buffer* vertexBuffer = fireBillboardSet->getGeometry()-> getPrimaryBuffer();

ID3D11DeviceContext* context;device->GetImmediateContext(&context);D3D11_MAPPED_SUBRESOURCE mappedVertexData;context->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedVertexData);

memcpy(mappedVertexData.pData, &particles.at(0), sizeof(Particle) * particles.size());context->Unmap(vertexBuffer, 0);context->Release();

Hirtelen tűnnek el

Megoldás

• Korfüggő méret, intenzitás és átlátszóság

gsBillboardstruct GsosBillboard{ float4 pos : SV_Position; float2 tex : TEXCOORD; float opacity : OPACITY;};

float s = input[0].age / input[0].lifespan;...output.opacity = 1 - abs(s*2-1);

// és mindenhol szorozzuk s-sel a szélességet és magasságot

#9.0

psFirefloat4 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)); color.a *= input.opacity; return color;}

#9.0

Simább tűz

fx/billboard.fxtechnique11 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 ); }}

#9.0

animate - rendezésusing namespace Egg::Math;struct CameraDepthComparator { float3 ahead; bool operator()(const Particle& a, const Particle& b) { return a.position.dot(ahead) > b.position.dot(ahead) + 0.01; }} comp = { firstPersonCam->getAhead() };std::sort(particles.begin(), particles.end(), comp);

Rendezéssel szép

400 részecske, kisebb alfa

top related