diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 5d5e6e4fb..a63671544 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -260,6 +260,7 @@ void EditorComponent::ChangeRenderPath(RENDERPATH path) lightWnd = new LightWindow(&GetGUI()); animWnd = new AnimationWindow(&GetGUI()); emitterWnd = new EmitterWindow(&GetGUI()); + emitterWnd->SetMaterialWnd(materialWnd); forceFieldWnd = new ForceFieldWindow(&GetGUI()); } void EditorComponent::DeleteWindows() diff --git a/Editor/EmitterWindow.cpp b/Editor/EmitterWindow.cpp index 3c96cf0bd..563a68180 100644 --- a/Editor/EmitterWindow.cpp +++ b/Editor/EmitterWindow.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "EmitterWindow.h" +#include "MaterialWindow.h" #include @@ -10,6 +11,7 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui) assert(GUI && "Invalid GUI!"); object = nullptr; + materialWnd = nullptr; float screenW = (float)wiRenderer::GetDevice()->GetScreenWidth(); @@ -233,6 +235,24 @@ EmitterWindow::EmitterWindow(wiGUI* gui) : GUI(gui) emitterWindow->AddWidget(emitMotionBlurSlider); + + materialSelectButton = new wiButton("Select Material"); + materialSelectButton->SetPos(XMFLOAT2(x, y += step)); + materialSelectButton->SetSize(XMFLOAT2(150, 30)); + materialSelectButton->OnClick([&](wiEventArgs args) { + if (materialWnd != nullptr) + { + auto emitter = GetEmitter(); + if (emitter != nullptr) + { + materialWnd->SetMaterial(emitter->material); + } + } + }); + materialSelectButton->SetTooltip("Select corresponding material in the Material Window."); + emitterWindow->AddWidget(materialSelectButton); + + emitterWindow->Translate(XMFLOAT3(200, 50, 0)); emitterWindow->SetVisible(false); @@ -297,6 +317,11 @@ void EmitterWindow::SetObject(Object* obj) } +void EmitterWindow::SetMaterialWnd(MaterialWindow* wnd) +{ + materialWnd = wnd; +} + wiEmittedParticle* EmitterWindow::GetEmitter() { if (object == nullptr) diff --git a/Editor/EmitterWindow.h b/Editor/EmitterWindow.h index c53453f25..ce5ede77a 100644 --- a/Editor/EmitterWindow.h +++ b/Editor/EmitterWindow.h @@ -11,6 +11,8 @@ class wiSlider; class wiComboBox; class wiColorPicker; +class MaterialWindow; + class EmitterWindow { public: @@ -18,12 +20,14 @@ public: ~EmitterWindow(); void SetObject(Object* obj); + void SetMaterialWnd(MaterialWindow* wnd); void UpdateData(); Object* object; wiEmittedParticle* GetEmitter(); wiGUI* GUI; + MaterialWindow* materialWnd; wiWindow* emitterWindow; @@ -42,6 +46,7 @@ public: wiSlider* emitRandomnessSlider; wiSlider* emitLifeRandomnessSlider; wiSlider* emitMotionBlurSlider; + wiButton* materialSelectButton; }; diff --git a/Editor/ObjectWindow.cpp b/Editor/ObjectWindow.cpp index 3b87c0d99..830a063be 100644 --- a/Editor/ObjectWindow.cpp +++ b/Editor/ObjectWindow.cpp @@ -20,6 +20,18 @@ ObjectWindow::ObjectWindow(wiGUI* gui) : GUI(gui) float x = 450; float y = 0; + renderableCheckBox = new wiCheckBox("Renderable: "); + renderableCheckBox->SetTooltip("Set object to be participating in rendering."); + renderableCheckBox->SetPos(XMFLOAT2(x, y += 30)); + renderableCheckBox->SetCheck(true); + renderableCheckBox->OnClick([&](wiEventArgs args) { + if (object != nullptr) + { + object->renderable = args.bValue; + } + }); + objectWindow->AddWidget(renderableCheckBox); + ditherSlider = new wiSlider(0, 1, 0, 1000, "Dither: "); ditherSlider->SetTooltip("Adjust dithered transparency of the object. This disables some optimizations so performance can be affected."); ditherSlider->SetSize(XMFLOAT2(100, 30)); @@ -225,6 +237,7 @@ void ObjectWindow::SetObject(Object* obj) if (object != nullptr) { + renderableCheckBox->SetCheck(object->renderable); ditherSlider->SetValue(object->transparency); if (object->rigidBody) diff --git a/Editor/ObjectWindow.h b/Editor/ObjectWindow.h index 4b1f6c419..e8ae9a411 100644 --- a/Editor/ObjectWindow.h +++ b/Editor/ObjectWindow.h @@ -24,6 +24,7 @@ public: wiWindow* objectWindow; + wiCheckBox* renderableCheckBox; wiSlider* ditherSlider; wiColorPicker* colorPicker; diff --git a/WickedEngine/ArchiveVersionHistory.txt b/WickedEngine/ArchiveVersionHistory.txt index 7e3818dd1..a2ec0487d 100644 --- a/WickedEngine/ArchiveVersionHistory.txt +++ b/WickedEngine/ArchiveVersionHistory.txt @@ -1,5 +1,6 @@ This file contains changelog of wiArchive versions +13: serialize object property: renderable 12: serialize emitter property: DEPTHCOLLISIONS 11: serialize additional emitter properties 10: serialize force fields diff --git a/WickedEngine/ShaderInterop_EmittedParticle.h b/WickedEngine/ShaderInterop_EmittedParticle.h index dd9badb62..f25f340a7 100644 --- a/WickedEngine/ShaderInterop_EmittedParticle.h +++ b/WickedEngine/ShaderInterop_EmittedParticle.h @@ -6,15 +6,12 @@ struct Particle { float3 position; - float size; - float rotation; - float3 velocity; float rotationalVelocity; + float3 velocity; float maxLife; float life; - float opacity; + uint color_mirror; float2 sizeBeginEnd; - float2 mirror; }; struct ParticleCounters @@ -45,7 +42,8 @@ CBUFFER(EmittedParticleCB, CBSLOT_OTHER_EMITTEDPARTICLE) float xParticleLifeSpanRandomness; float xParticleMotionBlurAmount; - float3 xPadding_EmitterCB; + uint xParticleColor; + float2 xPadding_EmitterCB; }; CBUFFER(SortConstants, 0) diff --git a/WickedEngine/emittedparticleHF.hlsli b/WickedEngine/emittedparticleHF.hlsli index b63a4644d..926308971 100644 --- a/WickedEngine/emittedparticleHF.hlsli +++ b/WickedEngine/emittedparticleHF.hlsli @@ -3,10 +3,11 @@ struct VertextoPixel { - float4 pos : SV_POSITION; - float4 pos2D : TEXCOORD0; - float2 tex : TEXCOORD1; - nointerpolation float2 opaSiz : TEXCOORD2; + float4 pos : SV_POSITION; + float4 pos2D : TEXCOORD0; + float2 tex : TEXCOORD1; + nointerpolation float size : TEXCOORD2; + nointerpolation uint color : TEXCOORD3; }; #endif // _EMITTEDPARTICLE_HF_ diff --git a/WickedEngine/emittedparticlePS.hlsl b/WickedEngine/emittedparticlePS.hlsl index 975d36902..c146cd515 100644 --- a/WickedEngine/emittedparticlePS.hlsl +++ b/WickedEngine/emittedparticlePS.hlsl @@ -2,17 +2,24 @@ #include "emittedparticleHF.hlsli" #include "depthConvertHF.hlsli" -float4 main(VertextoPixel PSIn) : SV_TARGET +float4 main(VertextoPixel input) : SV_TARGET { - float4 color = texture_0.Sample(sampler_linear_clamp,PSIn.tex); + float4 color = texture_0.Sample(sampler_linear_clamp,input.tex); clip(color.a - 1.0f / 255.0f); - float2 pTex = PSIn.pos2D.xy / PSIn.pos2D.w * float2(0.5f, -0.5f) + 0.5f; + float2 pTex = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; float4 depthScene = (texture_lineardepth.GatherRed(sampler_linear_clamp, pTex)); - float depthFragment = PSIn.pos2D.w; - float fade = saturate(1.0 / PSIn.opaSiz.y*(max(max(depthScene.x, depthScene.y), max(depthScene.z, depthScene.w)) - depthFragment)); + float depthFragment = input.pos2D.w; + float fade = saturate(1.0 / input.size*(max(max(depthScene.x, depthScene.y), max(depthScene.z, depthScene.w)) - depthFragment)); - color.a = saturate(color.a * PSIn.opaSiz.x * fade); + float4 inputColor; + inputColor.r = ((input.color >> 0) & 0x000000FF) / 255.0f; + inputColor.g = ((input.color >> 8) & 0x000000FF) / 255.0f; + inputColor.b = ((input.color >> 16) & 0x000000FF) / 255.0f; + inputColor.a = ((input.color >> 24) & 0x000000FF) / 255.0f; + + color.rgb *= inputColor.rgb; + color.a = saturate(color.a * inputColor.a * fade); return max(color, 0); } diff --git a/WickedEngine/emittedparticleVS.hlsl b/WickedEngine/emittedparticleVS.hlsl index e5a462b41..c7956da74 100644 --- a/WickedEngine/emittedparticleVS.hlsl +++ b/WickedEngine/emittedparticleVS.hlsl @@ -25,21 +25,27 @@ VertextoPixel main(uint fakeIndex : SV_VERTEXID) // load particle data: Particle particle = particleBuffer[aliveList[instanceID]]; + // calculate render properties from life: + float lifeLerp = 1 - particle.life / particle.maxLife; + float size = lerp(particle.sizeBeginEnd.x, particle.sizeBeginEnd.y, lifeLerp); + float opacity = saturate(lerp(1, 0, lifeLerp)); + float rotation = lifeLerp * particle.rotationalVelocity; + // expand the point into a billboard in view space: float3 quadPos = BILLBOARD[vertexID]; float2 uv = quadPos.xy * float2(0.5f, -0.5f) + 0.5f; - uv.x = particle.mirror.x > 0 ? 1.0f - uv.x : uv.x; - uv.y = particle.mirror.y > 0 ? 1.0f - uv.y : uv.y; + uv.x = particle.color_mirror & 0x10000000 ? 1.0f - uv.x : uv.x; + uv.y = particle.color_mirror & 0x20000000 ? 1.0f - uv.y : uv.y; // rotate the billboard: float2x2 rot = float2x2( - cos(particle.rotation), -sin(particle.rotation), - sin(particle.rotation), cos(particle.rotation) + cos(rotation), -sin(rotation), + sin(rotation), cos(rotation) ); quadPos.xy = mul(quadPos.xy, rot); // scale the billboard: - quadPos *= particle.size; + quadPos *= size; // scale the billboard along view space motion vector: float3 velocity = mul(particle.velocity, (float3x3)g_xCamera_View); @@ -53,7 +59,8 @@ VertextoPixel main(uint fakeIndex : SV_VERTEXID) Out.pos = mul(Out.pos, g_xCamera_Proj); Out.tex = uv; - Out.opaSiz = float2(particle.opacity, particle.size); + Out.size = size; + Out.color = (particle.color_mirror & 0x00FFFFFF) | (uint(opacity * 255.0f) << 24); Out.pos2D = Out.pos; return Out; diff --git a/WickedEngine/emittedparticle_emitCS.hlsl b/WickedEngine/emittedparticle_emitCS.hlsl index f8f03ff4c..d130bc2e4 100644 --- a/WickedEngine/emittedparticle_emitCS.hlsl +++ b/WickedEngine/emittedparticle_emitCS.hlsl @@ -75,19 +75,20 @@ void main(uint3 DTid : SV_DispatchThreadID) pos = mul(xEmitterWorld, float4(pos, 1)).xyz; nor = normalize(mul((float3x3)xEmitterWorld, nor)); + float particleStartingSize = xParticleSize + xParticleSize * (randoms.y - 0.5f) * xParticleRandomFactor; // create new particle: Particle particle; particle.position = pos; - particle.size = xParticleSize + xParticleSize * (randoms.y - 0.5f) * xParticleRandomFactor; - particle.rotation = xParticleRotation * (randoms.z - 0.5f) * xParticleRandomFactor; particle.velocity = (nor + (randoms.xyz - 0.5f) * xParticleRandomFactor) * xParticleNormalFactor; - particle.rotationalVelocity = particle.rotation; + particle.rotationalVelocity = xParticleRotation * (randoms.z - 0.5f) * xParticleRandomFactor; particle.maxLife = xParticleLifeSpan + xParticleLifeSpan * (randoms.x - 0.5f) * xParticleLifeSpanRandomness; particle.life = particle.maxLife; - particle.opacity = 1; - particle.sizeBeginEnd = float2(particle.size, particle.size * xParticleScaling); - particle.mirror = float2(randoms.x > 0.5f, randoms.y < 0.5f); + particle.sizeBeginEnd = float2(particleStartingSize, particleStartingSize * xParticleScaling); + particle.color_mirror = 0; + particle.color_mirror |= ((randoms.x > 0.5f) << 31) & 0x10000000; + particle.color_mirror |= ((randoms.y < 0.5f) << 30) & 0x20000000; + particle.color_mirror |= xParticleColor & 0x00FFFFFF; // new particle index retrieved from dead list (pop): diff --git a/WickedEngine/emittedparticle_simulateCS.hlsl b/WickedEngine/emittedparticle_simulateCS.hlsl index 56efb5a83..9ebb407a5 100644 --- a/WickedEngine/emittedparticle_simulateCS.hlsl +++ b/WickedEngine/emittedparticle_simulateCS.hlsl @@ -93,8 +93,11 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) float surfaceLinearDepth = getLinearDepth(depth0); float surfaceThickness = 1.5f; + float lifeLerp = 1 - particle.life / particle.maxLife; + float particleSize = lerp(particle.sizeBeginEnd.x, particle.sizeBeginEnd.y, lifeLerp); + // check if particle is colliding with the depth buffer, but not completely behind it: - if ((pos2D.w + particle.size > surfaceLinearDepth) && (pos2D.w - particle.size < surfaceLinearDepth + surfaceThickness)) + if ((pos2D.w + particleSize > surfaceLinearDepth) && (pos2D.w - particleSize < surfaceLinearDepth + surfaceThickness)) { // Calculate surface normal and bounce off the particle: float depth1 = texture_depth[pixel + uint2(1, 0)]; @@ -114,11 +117,6 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) #endif // DEPTHCOLLISIONS particle.position += particle.velocity * dt; - particle.rotation += particle.rotationalVelocity * dt; - - float lifeLerp = 1 - particle.life / particle.maxLife; - particle.size = lerp(particle.sizeBeginEnd.x, particle.sizeBeginEnd.y, lifeLerp); - particle.opacity = lerp(1, 0, lifeLerp); particle.life -= dt; diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index e82731e74..63e11c2c6 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -7,7 +7,7 @@ using namespace std; // this should always be only INCREMENTED and only if a new serialization is implemeted somewhere! -uint64_t __archiveVersion = 12; +uint64_t __archiveVersion = 13; // this is the version number of which below the archive is not compatible with the current version uint64_t __archiveVersionBarrier = 1; diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index ebb1df04f..09b8956d6 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -293,26 +293,27 @@ void wiEmittedParticle::UpdateRenderData(GRAPHICSTHREAD threadID) cb.xParticleSize = size; cb.xParticleMotionBlurAmount = motionBlurAmount; cb.xParticleRotation = rotation * XM_PI * 60; + cb.xParticleColor = wiMath::CompressColor(XMFLOAT4(material->baseColor.x, material->baseColor.y, material->baseColor.z, 1)); device->UpdateBuffer(constantBuffer, &cb, threadID); device->BindConstantBufferCS(constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), threadID); const GPUUnorderedResource* uavs[] = { - static_cast(particleBuffer), - static_cast(aliveList[0]), // CURRENT alivelist - static_cast(aliveList[1]), // NEW alivelist - static_cast(deadList), - static_cast(counterBuffer), - static_cast(indirectBuffers), - static_cast(distanceBuffer), + particleBuffer, + aliveList[0], // CURRENT alivelist + aliveList[1], // NEW alivelist + deadList, + counterBuffer, + indirectBuffers, + distanceBuffer, }; device->BindUnorderedAccessResourcesCS(uavs, 0, ARRAYSIZE(uavs), threadID); const GPUResource* resources[] = { wiTextureHelper::getInstance()->getRandom64x64(), - static_cast(&object->mesh->indexBuffer), - static_cast(&object->mesh->vertexBuffer_POS), - static_cast(&object->mesh->vertexBuffer_NOR), + &object->mesh->indexBuffer, + &object->mesh->vertexBuffer_POS, + &object->mesh->vertexBuffer_NOR, }; device->BindResourcesCS(resources, TEXSLOT_ONDEMAND0, ARRAYSIZE(resources), threadID); diff --git a/WickedEngine/wiLoader.cpp b/WickedEngine/wiLoader.cpp index e08bd65a1..7a17b66b8 100644 --- a/WickedEngine/wiLoader.cpp +++ b/WickedEngine/wiLoader.cpp @@ -413,8 +413,8 @@ void LoadWiObjects(const std::string& directory, const std::string& name, const file>>systemName>>visibleEmitter>>materialName>>size>>randfac>>norfac>>count>>life>>randlife; file>>scaleX>>scaleY>>rot; - if(visibleEmitter) objects.back()->emitterType=Object::EMITTER_VISIBLE; - else if(objects.back()->emitterType ==Object::NO_EMITTER) objects.back()->emitterType =Object::EMITTER_INVISIBLE; + //if(visibleEmitter) objects.back()->emitterType=Object::EMITTER_VISIBLE; + //else if(objects.back()->emitterType ==Object::NO_EMITTER) objects.back()->emitterType =Object::EMITTER_INVISIBLE; if(wiRenderer::EMITTERSENABLED){ stringstream identified_materialName(""); @@ -3881,7 +3881,7 @@ Object::~Object() void Object::init() { trail.resize(0); - emitterType = NO_EMITTER; + renderable = true; eParticleSystems.resize(0); hParticleSystems.resize(0); rigidBody = kinematic = false; @@ -4015,9 +4015,12 @@ bool Object::IsReflector() const int Object::GetRenderTypes() const { int retVal = RENDERTYPE::RENDERTYPE_VOID; - for (auto& x : mesh->subsets) + if (renderable) { - retVal |= x.material->GetRenderType(); + for (auto& x : mesh->subsets) + { + retVal |= x.material->GetRenderType(); + } } return retVal; } @@ -4044,9 +4047,8 @@ void Object::Serialize(wiArchive& archive) if (archive.IsReadMode()) { - int temp; - archive >> temp; - emitterType = (EmitterType)temp; + int unused; + archive >> unused; archive >> transparency; archive >> color; archive >> rigidBody; @@ -4074,10 +4076,16 @@ void Object::Serialize(wiArchive& archive) h->Serialize(archive); hParticleSystems.push_back(h); } + + if (archive.GetVersion() >= 13) + { + archive >> renderable; + } + } else { - archive << (int)emitterType; + archive << (int)0; archive << transparency; archive << color; archive << rigidBody; @@ -4099,6 +4107,12 @@ void Object::Serialize(wiArchive& archive) { x->Serialize(archive); } + + if (archive.GetVersion() >= 13) + { + archive << renderable; + } + } } #pragma endregion diff --git a/WickedEngine/wiLoader.h b/WickedEngine/wiLoader.h index bb66519b8..8bacba557 100644 --- a/WickedEngine/wiLoader.h +++ b/WickedEngine/wiLoader.h @@ -532,13 +532,9 @@ public: }; struct Object : public Streamable, public Transform { + bool renderable; + //PARTICLE - enum EmitterType{ - NO_EMITTER, - EMITTER_VISIBLE, - EMITTER_INVISIBLE, - }; - EmitterType emitterType; std::vector< wiEmittedParticle* > eParticleSystems; std::vector< wiHairParticle* > hParticleSystems; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 85ca413ac..62965fff3 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -2077,14 +2077,14 @@ void wiRenderer::UpdateRenderData(GRAPHICSTHREAD threadID) // Do the skinning const GPUResource* vbs[] = { - static_cast(&mesh->vertexBuffer_POS), - static_cast(&mesh->vertexBuffer_NOR), - static_cast(&mesh->vertexBuffer_BON), + &mesh->vertexBuffer_POS, + &mesh->vertexBuffer_NOR, + &mesh->vertexBuffer_BON, }; const GPUUnorderedResource* sos[] = { - static_cast(&mesh->streamoutBuffer_POS), - static_cast(&mesh->streamoutBuffer_NOR), - static_cast(&mesh->streamoutBuffer_PRE), + &mesh->streamoutBuffer_POS, + &mesh->streamoutBuffer_NOR, + &mesh->streamoutBuffer_PRE, }; GetDevice()->BindResourcesCS(vbs, SKINNINGSLOT_IN_VERTEX_POS, ARRAYSIZE(vbs), threadID); @@ -4113,7 +4113,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle int k = 0; for (const Object* instance : visibleInstances) { - if (instance->emitterType == Object::EmitterType::EMITTER_INVISIBLE || (occlusionCulling && instance->IsOccluded())) + if (occlusionCulling && instance->IsOccluded()) continue; const float impostorThreshold = instance->bounds.getRadius(); @@ -4295,7 +4295,7 @@ void wiRenderer::RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culle int k = 0; for (const Object* instance : visibleInstances) { - if (instance->emitterType == Object::EmitterType::EMITTER_INVISIBLE || (occlusionCulling && instance->IsOccluded())) + if (occlusionCulling && instance->IsOccluded()) continue; float dither = instance->transparency; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 1a86804b7..91b72a2bc 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 13; // minor bug fixes, alterations, refactors, updates - const int revision = 82; + const int revision = 83; long GetVersion()