diff --git a/WickedEngine/ConstantBufferMapping.h b/WickedEngine/ConstantBufferMapping.h index 1d427b4e4..e8bf583d5 100644 --- a/WickedEngine/ConstantBufferMapping.h +++ b/WickedEngine/ConstantBufferMapping.h @@ -22,6 +22,7 @@ #define CBSLOT_RENDERER_MATERIAL 7 #define CBSLOT_RENDERER_CUBEMAPRENDER 8 #define CBSLOT_RENDERER_VOLUMELIGHT 8 +#define CBSLOT_RENDERER_LENSFLARE 8 #define CBSLOT_RENDERER_DECAL 8 #define CBSLOT_RENDERER_TESSELLATION 8 #define CBSLOT_RENDERER_DISPATCHPARAMS 8 @@ -32,7 +33,6 @@ #define CBSLOT_OTHER_EMITTEDPARTICLE 8 #define CBSLOT_OTHER_HAIRPARTICLE 8 -#define CBSLOT_OTHER_LENSFLARE 8 #define CBSLOT_OTHER_FFTGENERATOR 8 #define CBSLOT_OTHER_OCEAN_SIMULATION_IMMUTABLE 8 #define CBSLOT_OTHER_OCEAN_SIMULATION_PERFRAME 9 diff --git a/WickedEngine/ShaderInterop_Image.h b/WickedEngine/ShaderInterop_Image.h new file mode 100644 index 000000000..b7771def5 --- /dev/null +++ b/WickedEngine/ShaderInterop_Image.h @@ -0,0 +1,21 @@ +#ifndef _SHADERINTEROP_IMAGE_H_ +#define _SHADERINTEROP_IMAGE_H_ +#include "ShaderInterop.h" + +CBUFFER(ImageCB, CBSLOT_IMAGE_IMAGE) +{ + float4x4 xTransform; + float4 xTexMulAdd; + float4 xColor; + float2 xPivot; + uint xMirror; + float xMipLevel; +}; +CBUFFER(PostProcessCB, CBSLOT_IMAGE_POSTPROCESS) +{ + float4 xPPParams0; + float4 xPPParams1; +}; + + +#endif // _SHADERINTEROP_IMAGE_H_ diff --git a/WickedEngine/ShaderInterop_Renderer.h b/WickedEngine/ShaderInterop_Renderer.h index 3d96e3090..fe466126b 100644 --- a/WickedEngine/ShaderInterop_Renderer.h +++ b/WickedEngine/ShaderInterop_Renderer.h @@ -155,6 +155,12 @@ CBUFFER(VolumeLightCB, CBSLOT_RENDERER_VOLUMELIGHT) float4 lightEnerdis; }; +CBUFFER(LensFlareCB, CBSLOT_RENDERER_LENSFLARE) +{ + float4 xSunPos; // light position + float4 xScreen; // screen dimensions +}; + CBUFFER(CubemapRenderCB, CBSLOT_RENDERER_CUBEMAPRENDER) { float4x4 xCubeShadowVP[6]; diff --git a/WickedEngine/WickedEngine.h b/WickedEngine/WickedEngine.h index b0b13a4b0..0b4066a31 100644 --- a/WickedEngine/WickedEngine.h +++ b/WickedEngine/WickedEngine.h @@ -37,7 +37,7 @@ #include "wiTextureHelper.h" #include "wiRandom.h" #include "wiColor.h" -#include "wiPhysics.h" +#include "wiPhysicsEngine.h" #include "wiEnums.h" #include "wiInitializer.h" #include "wiLua.h" diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems b/WickedEngine/WickedEngine_SHARED.vcxitems index a1a49b46d..793188f17 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems +++ b/WickedEngine/WickedEngine_SHARED.vcxitems @@ -235,6 +235,7 @@ + @@ -338,7 +339,7 @@ - + @@ -677,7 +678,7 @@ - + diff --git a/WickedEngine/WickedEngine_SHARED.vcxitems.filters b/WickedEngine/WickedEngine_SHARED.vcxitems.filters index 0b1d574e8..6431b0e01 100644 --- a/WickedEngine/WickedEngine_SHARED.vcxitems.filters +++ b/WickedEngine/WickedEngine_SHARED.vcxitems.filters @@ -1137,7 +1137,10 @@ ENGINE\Helpers - + + ENGINE\Graphics\GPUMapping + + ENGINE\Physics @@ -1928,7 +1931,7 @@ ENGINE\Scripting\LuaBindings - + ENGINE\Physics diff --git a/WickedEngine/imageHF.hlsli b/WickedEngine/imageHF.hlsli index 251bd3956..0b2383e1e 100644 --- a/WickedEngine/imageHF.hlsli +++ b/WickedEngine/imageHF.hlsli @@ -1,7 +1,7 @@ #ifndef _IMAGEHF_ #define _IMAGEHF_ #include "globals.hlsli" - +#include "ShaderInterop_Image.h" #define xTexture texture_0 #define xMaskTex texture_1 @@ -21,21 +21,5 @@ struct VertexToPixelPostProcess float2 tex : TEXCOORD0; }; - -CBUFFER(ImageCB, CBSLOT_IMAGE_IMAGE) -{ - float4x4 xTransform; - float4 xTexMulAdd; - float4 xColor; - float2 xPivot; - uint xMirror; - float xMipLevel; -}; -CBUFFER(PostProcessCB, CBSLOT_IMAGE_POSTPROCESS) -{ - float4 xPPParams0; - float4 xPPParams1; -}; - #endif // _IMAGEHF_ diff --git a/WickedEngine/lensFlareGS.hlsl b/WickedEngine/lensFlareGS.hlsl index 84ae9a845..02cfab9d5 100644 --- a/WickedEngine/lensFlareGS.hlsl +++ b/WickedEngine/lensFlareGS.hlsl @@ -1,11 +1,5 @@ #include "globals.hlsli" -// constant buffer -CBUFFER(LensFlareCB, CBSLOT_OTHER_LENSFLARE) -{ - float4 xSunPos; // light position - float4 xScreen; // screen dimensions -}; SAMPLERCOMPARISONSTATE(samplercmp, SSLOT_ONDEMAND0) struct InVert diff --git a/WickedEngine/wiECS.h b/WickedEngine/wiECS.h index c2b6680f2..9b190fed5 100644 --- a/WickedEngine/wiECS.h +++ b/WickedEngine/wiECS.h @@ -297,6 +297,17 @@ namespace wiECS return nullptr; } + // Retrieve component index by entity handle (if not exists, returns ~0 value) + inline size_t GetIndex(Entity entity) const + { + const auto it = lookup.find(entity); + if (it != lookup.end()) + { + return it->second; + } + return ~0; + } + // Retrieve the number of existing entries inline size_t GetCount() const { return components.size(); } diff --git a/WickedEngine/wiImage.cpp b/WickedEngine/wiImage.cpp index f6282690a..c6229a370 100644 --- a/WickedEngine/wiImage.cpp +++ b/WickedEngine/wiImage.cpp @@ -6,6 +6,7 @@ #include "SamplerMapping.h" #include "ResourceMapping.h" #include "wiSceneSystem.h" +#include "ShaderInterop_Image.h" #include @@ -397,12 +398,12 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR if(!effects.process.active && !effects.bloom.separate && !effects.sunPos.x && !effects.sunPos.y){ if (effects.typeFlag == SCREEN) { - cb.mTransform = XMMatrixTranspose( + XMStoreFloat4x4(&cb.xTransform, XMMatrixTranspose( XMMatrixScaling(effects.scale.x*effects.siz.x, effects.scale.y*effects.siz.y, 1) * XMMatrixRotationZ(effects.rotation) * XMMatrixTranslation(effects.pos.x, effects.pos.y, 0) * device->GetScreenProjection() - ); + )); } else if (effects.typeFlag == WORLD) { @@ -429,27 +430,27 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR projection.r[2] = XMVectorSetX(projection.r[2], 0); projection.r[2] = XMVectorSetY(projection.r[2], 0); - cb.mTransform = XMMatrixTranspose( + XMStoreFloat4x4(&cb.xTransform, XMMatrixTranspose( XMMatrixScaling(effects.scale.x*effects.siz.x, -1 * effects.scale.y*effects.siz.y, 1) *XMMatrixRotationZ(effects.rotation) *faceRot *XMMatrixTranslation(effects.pos.x, effects.pos.y, effects.pos.z) *view * projection - ); + )); } // todo: effects.drawRec -> texmuladd! - cb.mTexMulAdd = XMFLOAT4(1,1,effects.texOffset.x, effects.texOffset.y); - cb.mColor = effects.col; - cb.mColor.x *= 1 - effects.fade; - cb.mColor.y *= 1 - effects.fade; - cb.mColor.z *= 1 - effects.fade; - cb.mColor.w *= effects.opacity; - cb.mPivot = effects.pivot; - cb.mMirror = effects.mirror; - cb.mPivot = effects.pivot; - cb.mMipLevel = effects.mipLevel; + cb.xTexMulAdd = XMFLOAT4(1,1,effects.texOffset.x, effects.texOffset.y); + cb.xColor = effects.col; + cb.xColor.x *= 1 - effects.fade; + cb.xColor.y *= 1 - effects.fade; + cb.xColor.z *= 1 - effects.fade; + cb.xColor.w *= effects.opacity; + cb.xPivot = effects.pivot; + cb.xMirror = effects.mirror; + cb.xPivot = effects.pivot; + cb.xMipLevel = effects.mipLevel; device->UpdateBuffer(&constantBuffer, &cb, threadID); @@ -501,21 +502,21 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR { targetShader = POSTPROCESS_OUTLINE; - prcb.params0[1] = effects.process.outline ? 1.0f : 0.0f; + prcb.xPPParams0.y = effects.process.outline ? 1.0f : 0.0f; device->UpdateBuffer(&processCb, &prcb, threadID); } else if (effects.process.motionBlur) { targetShader = POSTPROCESS_MOTIONBLUR; - prcb.params0[0] = effects.process.motionBlur ? 1.0f : 0.0f; + prcb.xPPParams0.x = effects.process.motionBlur ? 1.0f : 0.0f; device->UpdateBuffer(&processCb, &prcb, threadID); } else if (effects.process.dofStrength) { targetShader = POSTPROCESS_DEPTHOFFIELD; - prcb.params0[2] = effects.process.dofStrength; + prcb.xPPParams0.z = effects.process.dofStrength; device->UpdateBuffer(&processCb, &prcb, threadID); } else if (effects.process.fxaa) @@ -550,17 +551,17 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR { targetShader = POSTPROCESS_SSSS; - prcb.params0[0] = effects.process.ssss.x; - prcb.params0[1] = effects.process.ssss.y; + prcb.xPPParams0.x = effects.process.ssss.x; + prcb.xPPParams0.y = effects.process.ssss.y; device->UpdateBuffer(&processCb, &prcb, threadID); } else if (effects.bloom.separate) { targetShader = POSTPROCESS_BLOOMSEPARATE; - prcb.params1[0] = effects.bloom.separate ? 1.0f : 0.0f; - prcb.params1[1] = effects.bloom.threshold; - prcb.params1[2] = effects.bloom.saturation; + prcb.xPPParams1.x = effects.bloom.separate ? 1.0f : 0.0f; + prcb.xPPParams1.y = effects.bloom.threshold; + prcb.xPPParams1.z = effects.bloom.saturation; device->UpdateBuffer(&processCb, &prcb, threadID); } else if (effects.process.reprojectDepthBuffer) @@ -579,7 +580,7 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR { targetShader = POSTPROCESS_SHARPEN; - prcb.params0[0] = effects.process.sharpen; + prcb.xPPParams0.x = effects.process.sharpen; device->UpdateBuffer(&processCb, &prcb, threadID); } else @@ -596,12 +597,12 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR fullScreenEffect = true; //Density|Weight|Decay|Exposure - prcb.params0[0] = 0.65f; - prcb.params0[1] = 0.25f; - prcb.params0[2] = 0.945f; - prcb.params0[3] = 0.2f; - prcb.params1[0] = effects.sunPos.x; - prcb.params1[1] = effects.sunPos.y; + prcb.xPPParams0.x = 0.65f; + prcb.xPPParams0.y = 0.25f; + prcb.xPPParams0.z = 0.945f; + prcb.xPPParams0.w = 0.2f; + prcb.xPPParams1.x = effects.sunPos.x; + prcb.xPPParams1.y = effects.sunPos.y; device->UpdateBuffer(&processCb,&prcb,threadID); @@ -620,12 +621,12 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR if(effects.blurDir==0) { device->BindGraphicsPSO(&postprocessPSO[POSTPROCESS_BLUR_H], threadID); - prcb.params1[3] = 1.0f / wiRenderer::GetInternalResolution().x; + prcb.xPPParams1.z = 1.0f / wiRenderer::GetInternalResolution().x; } else { device->BindGraphicsPSO(&postprocessPSO[POSTPROCESS_BLUR_V], threadID); - prcb.params1[3] = 1.0f / wiRenderer::GetInternalResolution().y; + prcb.xPPParams1.z = 1.0f / wiRenderer::GetInternalResolution().y; } static float weight0 = 1.0f; @@ -634,13 +635,13 @@ void wiImage::Draw(Texture2D* texture, const wiImageEffects& effects,GRAPHICSTHR static float weight3 = 0.18f; static float weight4 = 0.1f; const float normalization = 1.0f / (weight0 + 2.0f * (weight1 + weight2 + weight3 + weight4)); - prcb.params0[0] = weight0 * normalization; - prcb.params0[1] = weight1 * normalization; - prcb.params0[2] = weight2 * normalization; - prcb.params0[3] = weight3 * normalization; - prcb.params1[0] = weight4 * normalization; - prcb.params1[1] = effects.blur; - prcb.params1[2] = effects.mipLevel; + prcb.xPPParams0.x = weight0 * normalization; + prcb.xPPParams0.y = weight1 * normalization; + prcb.xPPParams0.z = weight2 * normalization; + prcb.xPPParams0.w = weight3 * normalization; + prcb.xPPParams1.x = weight4 * normalization; + prcb.xPPParams1.y = effects.blur; + prcb.xPPParams1.z = effects.mipLevel; device->UpdateBuffer(&processCb, &prcb, threadID); diff --git a/WickedEngine/wiImage.h b/WickedEngine/wiImage.h index 17c568be6..108b07420 100644 --- a/WickedEngine/wiImage.h +++ b/WickedEngine/wiImage.h @@ -9,21 +9,6 @@ enum BLENDMODE; class wiImage { protected: - CBUFFER(ImageCB, CBSLOT_IMAGE_IMAGE) - { - XMMATRIX mTransform; - XMFLOAT4 mTexMulAdd; - XMFLOAT4 mColor; - XMFLOAT2 mPivot; - UINT mMirror; - float mMipLevel; - }; - CBUFFER(PostProcessCB, CBSLOT_IMAGE_POSTPROCESS) - { - float params0[4]; - float params1[4]; - }; - static wiGraphicsTypes::GPUBuffer constantBuffer, processCb; static wiGraphicsTypes::VertexShader* vertexShader; diff --git a/WickedEngine/wiInitializer.cpp b/WickedEngine/wiInitializer.cpp index 28e49097c..260af5fee 100644 --- a/WickedEngine/wiInitializer.cpp +++ b/WickedEngine/wiInitializer.cpp @@ -11,7 +11,7 @@ #include "wiHelper.h" #include "wiWidget.h" #include "wiGPUSortLib.h" -#include "wiPhysics.h" +#include "wiPhysicsEngine.h" using namespace std; diff --git a/WickedEngine/wiLensFlare.cpp b/WickedEngine/wiLensFlare.cpp index 698417089..095c9fb00 100644 --- a/WickedEngine/wiLensFlare.cpp +++ b/WickedEngine/wiLensFlare.cpp @@ -2,6 +2,7 @@ #include "wiRenderer.h" #include "wiResourceManager.h" #include "ResourceMapping.h" +#include "ShaderInterop_Renderer.h" using namespace wiGraphicsTypes; @@ -36,12 +37,12 @@ void wiLensFlare::Draw(GRAPHICSTHREAD threadID, const XMVECTOR& lightPos, const device->BindGraphicsPSO(&PSO, threadID); - ConstantBuffer cb; - cb.mSunPos = lightPos / XMVectorSet((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 1, 1); - cb.mScreen = XMFLOAT4((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0, 0); + LensFlareCB cb; + XMStoreFloat4(&cb.xSunPos, lightPos / XMVectorSet((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 1, 1)); + cb.xScreen = XMFLOAT4((float)wiRenderer::GetInternalResolution().x, (float)wiRenderer::GetInternalResolution().y, 0, 0); device->UpdateBuffer(constantBuffer,&cb,threadID); - device->BindConstantBuffer(GS, constantBuffer, CB_GETBINDSLOT(ConstantBuffer),threadID); + device->BindConstantBuffer(GS, constantBuffer, CB_GETBINDSLOT(LensFlareCB),threadID); int i=0; @@ -95,7 +96,7 @@ void wiLensFlare::SetUpCB() GPUBufferDesc bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = USAGE_DYNAMIC; - bd.ByteWidth = sizeof(ConstantBuffer); + bd.ByteWidth = sizeof(LensFlareCB); bd.BindFlags = BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = CPU_ACCESS_WRITE; constantBuffer = new GPUBuffer; diff --git a/WickedEngine/wiLensFlare.h b/WickedEngine/wiLensFlare.h index 558475e33..45bdf6f06 100644 --- a/WickedEngine/wiLensFlare.h +++ b/WickedEngine/wiLensFlare.h @@ -2,7 +2,6 @@ #define LENSFLARE #include "CommonInclude.h" #include "wiGraphicsAPI.h" -#include "ShaderInterop.h" class wiLensFlare { @@ -17,12 +16,6 @@ private: static wiGraphicsTypes::Sampler *samplercmp; static wiGraphicsTypes::GraphicsPSO PSO; - CBUFFER(ConstantBuffer, CBSLOT_OTHER_LENSFLARE) - { - XMVECTOR mSunPos; - XMFLOAT4 mScreen; - }; - public: static void LoadShaders(); private: diff --git a/WickedEngine/wiPHYSICS.h b/WickedEngine/wiPhysicsEngine.h similarity index 100% rename from WickedEngine/wiPHYSICS.h rename to WickedEngine/wiPhysicsEngine.h diff --git a/WickedEngine/wiPhysics_Bullet.cpp b/WickedEngine/wiPhysicsEngine_Bullet.cpp similarity index 99% rename from WickedEngine/wiPhysics_Bullet.cpp rename to WickedEngine/wiPhysicsEngine_Bullet.cpp index da7205e2a..49adc38aa 100644 --- a/WickedEngine/wiPhysics_Bullet.cpp +++ b/WickedEngine/wiPhysicsEngine_Bullet.cpp @@ -1,4 +1,4 @@ -#include "wiPhysics.h" +#include "wiPhysicsEngine.h" #include "wiSceneSystem.h" #include "wiProfiler.h" diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 9c8bfdf6e..799101164 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -12,7 +12,6 @@ #include "wiMath.h" #include "wiLensFlare.h" #include "wiTextureHelper.h" -#include "wiPHYSICS.h" #include "wiCube.h" #include "wiEnums.h" #include "wiRandom.h" @@ -156,11 +155,86 @@ GraphicsDevice* GetDevice() } +struct RenderBatch +{ + uint32_t hash; + uint32_t instance; + + inline void Create(size_t meshIndex, size_t instanceIndex, float distance) + { + hash = 0; + + assert(meshIndex < 0x00FFFFFF); + hash |= (uint32_t)(meshIndex & 0x00FFFFFF) << 8; + hash |= ((uint32_t)(distance)) & 0xFF; + + instance = (uint32_t)instanceIndex; + } + + inline size_t GetMeshIndex() const + { + return (size_t)((hash >> 8) & 0x00FFFFFF); + } + inline size_t GetInstanceIndex() const + { + return instance; + } + inline float GetDistance() const + { + return (float)(hash & 0xFF); + } +}; +struct RenderQueue +{ + RenderBatch* batchArray = nullptr; + size_t batchCount = 0; + + enum RenderQueueSortType + { + SORT_FRONT_TO_BACK, + SORT_BACK_TO_FRONT, + }; + + inline bool empty() const { return batchArray == nullptr || batchCount == 0; } + inline void add(RenderBatch* item) + { + assert(item != nullptr); + if (empty()) + { + batchArray = item; + } + batchCount++; + } + inline void sort(RenderQueueSortType sortType = SORT_FRONT_TO_BACK) + { + if (batchCount > 1) + { + std::sort(batchArray, batchArray + batchCount, [sortType](const RenderBatch& a, const RenderBatch& b) -> bool { + return ((sortType == SORT_FRONT_TO_BACK) ? (a.hash < b.hash) : (a.hash > b.hash)); + }); + + //for (size_t i = 0; i < batchCount - 1; ++i) + //{ + // for (size_t j = i + 1; j < batchCount; ++j) + // { + // bool swap = false; + // swap = sortType == SORT_FRONT_TO_BACK && batchArray[i].hash > batchArray[j].hash; + // swap = sortType == SORT_BACK_TO_FRONT && batchArray[i].hash < batchArray[j].hash; + + // if (swap) + // { + // RenderBatch tmp = batchArray[i]; + // batchArray[i] = batchArray[j]; + // batchArray[j] = tmp; + // } + // } + //} + } + } +}; struct FrameCulling { Frustum frustum; - CulledCollection culledRenderer_opaque; - CulledCollection culledRenderer_transparent; vector culledObjects; vector culledLights; vector culledDecals; @@ -168,8 +242,6 @@ struct FrameCulling void Clear() { - culledRenderer_opaque.clear(); - culledRenderer_transparent.clear(); culledObjects.clear(); culledLights.clear(); culledDecals.clear(); @@ -178,12 +250,6 @@ struct FrameCulling }; unordered_map frameCullings; -struct RenderBatch -{ - Entity meshID; - Entity instanceID; -}; - GFX_STRUCT Instance { XMFLOAT4A mat0; @@ -1131,6 +1197,443 @@ enum TILEDLIGHTING_DEBUG ComputePSO* CPSO_tiledlighting[TILEDLIGHTING_TYPE_COUNT][TILEDLIGHTING_CULLING_COUNT][TILEDLIGHTING_DEBUG_COUNT] = {}; ComputePSO* CPSO[CSTYPE_LAST] = {}; +void RenderMeshes(const XMFLOAT3& eye, const RenderQueue& renderQueue, SHADERTYPE shaderType, UINT renderTypeFlags, GRAPHICSTHREAD threadID, + bool tessellation = false, bool occlusionCulling = false) +{ + // Intensive section, refactor and optimize! + + if (!renderQueue.empty()) + { + GraphicsDevice* device = GetDevice(); + Scene& scene = GetScene(); + + device->EventBegin("RenderMeshes", threadID); + + tessellation = tessellation && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION); + + const XMFLOAT4X4 __identityMat = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); + + struct InstBuf + { + Instance instance; + InstancePrev instancePrev; + }; + + const bool advancedVBRequest = + !IsWireRender() && + (shaderType == SHADERTYPE_FORWARD || + shaderType == SHADERTYPE_DEFERRED || + shaderType == SHADERTYPE_TILEDFORWARD); + + const bool easyTextureBind = + shaderType == SHADERTYPE_TEXTURE || + shaderType == SHADERTYPE_SHADOW || + shaderType == SHADERTYPE_SHADOWCUBE || + shaderType == SHADERTYPE_DEPTHONLY || + shaderType == SHADERTYPE_VOXELIZE; + + GraphicsPSO* impostorRequest = GetImpostorPSO(shaderType); + + // Render impostors: + if (impostorRequest != nullptr) + { + bool impostorGraphicsStateComplete = false; + + for (size_t batchID = 0; batchID < renderQueue.batchCount; ++batchID) + { + const RenderBatch& batch = renderQueue.batchArray[batchID]; + + const size_t meshIndex = batch.GetMeshIndex(); + const MeshComponent& mesh = scene.meshes[meshIndex]; + if (!mesh.IsRenderable() || !mesh.HasImpostor()) + { + continue; + } + + //const auto& visibleInstances = iter->second; + + UINT instancesOffset; + size_t alloc_size = /*visibleInstances.size()*/ 1; + alloc_size *= advancedVBRequest ? sizeof(InstBuf) : sizeof(Instance); + void* instances = device->AllocateFromRingBuffer(dynamicVertexBufferPool, alloc_size, instancesOffset, threadID); + + int k = 0; + for (size_t instanceID = 0; instanceID < 1; ++instanceID) + { + size_t instanceIndex = batch.GetInstanceIndex(); + const ObjectComponent& instance = scene.objects[instanceIndex]; + if (occlusionCulling && instance.IsOccluded()) + continue; + + const AABB& aabb = scene.aabb_objects[instanceIndex]; + + const float impostorThreshold = aabb.getRadius(); + float dist = wiMath::Distance(eye, aabb.getCenter()); + float dither = instance.GetTransparency(); + dither = wiMath::SmoothStep(1.0f, dither, wiMath::Clamp((dist - mesh.impostorDistance) / impostorThreshold, 0, 1)); + if (dither > 1.0f - FLT_EPSILON) + continue; + + XMMATRIX boxMat = mesh.aabb.getAsBoxMatrix(); + + Entity objectEntity = scene.objects.GetEntity(instanceIndex); + const TransformComponent& transform = *scene.transforms.GetComponent(objectEntity); + + XMFLOAT4X4 tempMat; + XMStoreFloat4x4(&tempMat, boxMat*XMLoadFloat4x4(&transform.world)); + + if (advancedVBRequest) + { + ((volatile InstBuf*)instances)[k].instance.Create(tempMat, instance.color, dither); + + const PreviousFrameTransformComponent& prev_transform = *scene.prev_transforms.GetComponent(objectEntity); + XMStoreFloat4x4(&tempMat, boxMat*XMLoadFloat4x4(&prev_transform.world_prev)); + ((volatile InstBuf*)instances)[k].instancePrev.Create(tempMat); + } + else + { + ((volatile Instance*)instances)[k].Create(tempMat, instance.color, dither); + } + + ++k; + } + + device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); + + if (k < 1) + continue; + + if (!advancedVBRequest || IsWireRender()) + { + GPUBuffer* vbs[] = { + &impostorVB_POS, + &impostorVB_TEX, + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + sizeof(Instance) + }; + UINT offsets[] = { + 0, + 0, + instancesOffset + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + } + else + { + GPUBuffer* vbs[] = { + &impostorVB_POS, + &impostorVB_TEX, + &impostorVB_POS, + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + sizeof(MeshComponent::Vertex_POS), + sizeof(InstBuf) + }; + UINT offsets[] = { + 0, + 0, + 0, + instancesOffset + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + } + + GPUResource* res[] = { + mesh.impostorTarget.GetTexture(0), + mesh.impostorTarget.GetTexture(1), + mesh.impostorTarget.GetTexture(2) + }; + device->BindResources(PS, res, TEXSLOT_ONDEMAND0, (easyTextureBind ? 1 : ARRAYSIZE(res)), threadID); + + if (!impostorGraphicsStateComplete) + { + device->BindGraphicsPSO(impostorRequest, threadID); + device->BindConstantBuffer(PS, &impostorMaterialCB, CB_GETBINDSLOT(MaterialCB), threadID); + SetAlphaRef(0.75f, threadID); + impostorGraphicsStateComplete = true; + } + + device->DrawInstanced(6 * 6, k, 0, 0, threadID); // 6 * 6: see MeshComponent::CreateImpostorVB function + + } + } + + + PRIMITIVETOPOLOGY prevTOPOLOGY = TRIANGLELIST; + + // Render meshes: + for (size_t batchID = 0; batchID < renderQueue.batchCount; ++batchID) + { + const RenderBatch& batch = renderQueue.batchArray[batchID]; + + const size_t meshIndex = batch.GetMeshIndex(); + const MeshComponent& mesh = scene.meshes[meshIndex]; + if (!mesh.IsRenderable()) + { + continue; + } + + //const auto& visibleInstances = iter->second; + + const float tessF = mesh.GetTessellationFactor(); + const bool tessellatorRequested = tessF > 0 && tessellation; + + if (tessellatorRequested) + { + TessellationCB tessCB; + tessCB.g_f4TessFactors = XMFLOAT4(tessF, tessF, tessF, tessF); + device->UpdateBuffer(constantBuffers[CBTYPE_TESSELLATION], &tessCB, threadID); + device->BindConstantBuffer(HS, constantBuffers[CBTYPE_TESSELLATION], CBSLOT_RENDERER_TESSELLATION, threadID); + } + + bool forceAlphaTestForDithering = false; + + UINT instancesOffset; + size_t alloc_size = /*visibleInstances.size()*/1; + alloc_size *= advancedVBRequest ? sizeof(InstBuf) : sizeof(Instance); + void* instances = device->AllocateFromRingBuffer(dynamicVertexBufferPool, alloc_size, instancesOffset, threadID); + + int k = 0; + for (size_t instanceID = 0; instanceID < 1; ++instanceID) + { + size_t instanceIndex = batch.GetInstanceIndex(); + const ObjectComponent& instance = scene.objects[instanceIndex]; + if (occlusionCulling && instance.IsOccluded()) + continue; + + float dither = instance.GetTransparency(); + if (impostorRequest != nullptr) + { + // fade out to impostor... + const AABB& aabb = scene.aabb_objects[instanceIndex]; + const float impostorThreshold = aabb.getRadius(); + float dist = wiMath::Distance(eye, aabb.getCenter()); + if (mesh.HasImpostor()) + dither = wiMath::SmoothStep(dither, 1.0f, wiMath::Clamp((dist - impostorThreshold - mesh.impostorDistance) / impostorThreshold, 0, 1)); + } + if (dither > 1.0f - FLT_EPSILON) + continue; + + forceAlphaTestForDithering = forceAlphaTestForDithering || (dither > 0); + + Entity objectEntity = scene.objects.GetEntity(instanceIndex); + const TransformComponent& transform = *scene.transforms.GetComponent(objectEntity); + + if (advancedVBRequest || tessellatorRequested) + { + ((volatile InstBuf*)instances)[k].instance.Create(transform.world, instance.color); + + const PreviousFrameTransformComponent& prev_transform = *scene.prev_transforms.GetComponent(objectEntity); + ((volatile InstBuf*)instances)[k].instancePrev.Create(prev_transform.world_prev); + } + else + { + ((volatile Instance*)instances)[k].Create(transform.world, instance.color, dither); + } + + ++k; + + } + + device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); + + if (k < 1) + continue; + + device->BindIndexBuffer(mesh.indexBuffer.get(), mesh.GetIndexFormat(), 0, threadID); + + enum class BOUNDVERTEXBUFFERTYPE + { + NOTHING, + POSITION, + POSITION_TEXCOORD, + EVERYTHING, + }; + BOUNDVERTEXBUFFERTYPE boundVBType_Prev = BOUNDVERTEXBUFFERTYPE::NOTHING; + + for (const MeshComponent::MeshSubset& subset : mesh.subsets) + { + if (subset.indexCount == 0) + { + continue; + } + const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); + + GraphicsPSO* pso = /*material.customShader == nullptr ?*/ GetObjectPSO(shaderType, mesh.IsDoubleSided(), tessellatorRequested, material, forceAlphaTestForDithering) /*: material.customShader->passes[shaderType].pso*/; + if (pso == nullptr) + { + continue; + } + + bool subsetRenderable = false; + + if (renderTypeFlags & RENDERTYPE_OPAQUE) + { + subsetRenderable = subsetRenderable || (!material.IsTransparent() && !material.IsWater()); + } + if (renderTypeFlags & RENDERTYPE_TRANSPARENT) + { + subsetRenderable = subsetRenderable || material.IsTransparent(); + } + if (renderTypeFlags & RENDERTYPE_WATER) + { + subsetRenderable = subsetRenderable || material.IsWater(); + } + if (shaderType == SHADERTYPE_SHADOW || shaderType == SHADERTYPE_SHADOWCUBE) + { + subsetRenderable = subsetRenderable && material.IsCastingShadow(); + } + + if (!subsetRenderable) + { + continue; + } + + BOUNDVERTEXBUFFERTYPE boundVBType; + if (advancedVBRequest || tessellatorRequested) + { + boundVBType = BOUNDVERTEXBUFFERTYPE::EVERYTHING; + } + else + { + // simple vertex buffers are used in some passes (note: tessellator requires more attributes) + if ((shaderType == SHADERTYPE_DEPTHONLY || shaderType == SHADERTYPE_SHADOW || shaderType == SHADERTYPE_SHADOWCUBE) && !material.IsAlphaTestEnabled() && !forceAlphaTestForDithering) + { + if (shaderType == SHADERTYPE_SHADOW && material.IsTransparent()) + { + boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; + } + else + { + // bypass texcoord stream for non alphatested shadows and zprepass + boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION; + } + } + else + { + boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; + } + } + + if (material.IsWater()) + { + boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; + } + + if (IsWireRender()) + { + boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; + } + + // Only bind vertex buffers when the layout changes + if (boundVBType != boundVBType_Prev) + { + // Assemble the required vertex buffer: + switch (boundVBType) + { + case BOUNDVERTEXBUFFERTYPE::POSITION: + { + GPUBuffer* vbs[] = { + mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(Instance) + }; + UINT offsets[] = { + 0, + instancesOffset + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + } + break; + case BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD: + { + GPUBuffer* vbs[] = { + mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), + mesh.vertexBuffer_TEX.get(), + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + sizeof(Instance) + }; + UINT offsets[] = { + 0, + 0, + instancesOffset + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + } + break; + case BOUNDVERTEXBUFFERTYPE::EVERYTHING: + { + GPUBuffer* vbs[] = { + mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), + mesh.vertexBuffer_TEX.get(), + mesh.streamoutBuffer_PRE.get() != nullptr ? mesh.streamoutBuffer_PRE.get() : mesh.vertexBuffer_POS.get(), + dynamicVertexBufferPool + }; + UINT strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + sizeof(MeshComponent::Vertex_POS), + sizeof(InstBuf) + }; + UINT offsets[] = { + 0, + 0, + 0, + instancesOffset + }; + device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); + } + break; + default: + assert(0); + break; + } + } + boundVBType_Prev = boundVBType; + + device->BindConstantBuffer(PS, material.constantBuffer.get(), CB_GETBINDSLOT(MaterialCB), threadID); + + device->BindStencilRef(material.GetStencilRef(), threadID); + + device->BindGraphicsPSO(pso, threadID); + + GPUResource* res[] = { + material.GetBaseColorMap(), + material.GetNormalMap(), + material.GetSurfaceMap(), + material.GetDisplacementMap(), + }; + device->BindResources(PS, res, TEXSLOT_ONDEMAND0, (easyTextureBind ? 2 : ARRAYSIZE(res)), threadID); + + SetAlphaRef(material.alphaRef, threadID); + + device->DrawIndexedInstanced((int)subset.indexCount, k, subset.indexOffset, 0, 0, threadID); + } + + } + + ResetAlphaRef(threadID); + + device->EventEnd(threadID); + } +} + + + void LoadShaders() { GraphicsDevice* device = GetDevice(); @@ -1152,30 +1655,30 @@ void LoadShaders() VertexLayoutDesc layout[] = { { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "PREVPOS", 0, MeshComponent::Vertex_POS::FORMAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "PREVPOS", 0, MeshComponent::Vertex_POS::FORMAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATIPREV", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATIPREV", 1, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATIPREV", 2, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATIPREV", 0, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATIPREV", 1, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATIPREV", 2, FORMAT_R32G32B32A32_FLOAT, 3, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, }; vertexShaders[VSTYPE_OBJECT_COMMON] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "objectVS_common.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_OBJECT_COMMON]->code.data, vertexShaders[VSTYPE_OBJECT_COMMON]->code.size, vertexLayouts[VLTYPE_OBJECT_ALL]); - + } { VertexLayoutDesc layout[] = { { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, }; vertexShaders[VSTYPE_OBJECT_POSITIONSTREAM] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "objectVS_positionstream.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_OBJECT_POSITIONSTREAM]->code.data, vertexShaders[VSTYPE_OBJECT_POSITIONSTREAM]->code.size, vertexLayouts[VLTYPE_OBJECT_POS]); @@ -1185,12 +1688,12 @@ void LoadShaders() VertexLayoutDesc layout[] = { { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, }; vertexShaders[VSTYPE_OBJECT_SIMPLE] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "objectVS_simple.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_OBJECT_SIMPLE]->code.data, vertexShaders[VSTYPE_OBJECT_SIMPLE]->code.size, vertexLayouts[VLTYPE_OBJECT_POS_TEX]); @@ -1201,10 +1704,10 @@ void LoadShaders() { { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, }; vertexShaders[VSTYPE_SHADOW] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "shadowVS.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_SHADOW]->code.data, vertexShaders[VSTYPE_SHADOW]->code.size, vertexLayouts[VLTYPE_SHADOW_POS]); @@ -1214,12 +1717,12 @@ void LoadShaders() VertexLayoutDesc layout[] = { { "POSITION_NORMAL_SUBSETINDEX", 0, MeshComponent::Vertex_POS::FORMAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, MeshComponent::Vertex_TEX::FORMAT, 1, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, - { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 1, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "MATI", 2, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, + { "COLOR_DITHER", 0, FORMAT_R32G32B32A32_FLOAT, 2, APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA, 1 }, }; vertexShaders[VSTYPE_SHADOW_ALPHATEST] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "shadowVS_alphatest.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_SHADOW_ALPHATEST]->code.data, vertexShaders[VSTYPE_SHADOW_ALPHATEST]->code.size, vertexLayouts[VLTYPE_SHADOW_POS_TEX]); @@ -1233,7 +1736,7 @@ void LoadShaders() VertexLayoutDesc layout[] = { { "POSITION", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, }; vertexShaders[VSTYPE_LINE] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "linesVS.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_LINE]->code.data, vertexShaders[VSTYPE_LINE]->code.size, vertexLayouts[VLTYPE_LINE]); @@ -1244,8 +1747,8 @@ void LoadShaders() VertexLayoutDesc layout[] = { { "POSITION", 0, FORMAT_R32G32B32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, FORMAT_R32G32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 1, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, FORMAT_R32G32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, FORMAT_R32G32B32A32_FLOAT, 0, APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA, 0 }, }; vertexShaders[VSTYPE_TRAIL] = static_cast(wiResourceManager::GetShaderManager()->add(SHADERPATH + "trailVS.cso", wiResourceManager::VERTEXSHADER)); device->CreateInputLayout(layout, ARRAYSIZE(layout), vertexShaders[VSTYPE_TRAIL]->code.data, vertexShaders[VSTYPE_TRAIL]->code.size, vertexLayouts[VLTYPE_TRAIL]); @@ -2273,40 +2776,40 @@ void SetUpStates() samplerDesc.AddressV = TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = TEXTURE_ADDRESS_WRAP; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_LINEAR_WRAP]); - + samplerDesc.Filter = FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = TEXTURE_ADDRESS_MIRROR; samplerDesc.AddressV = TEXTURE_ADDRESS_MIRROR; samplerDesc.AddressW = TEXTURE_ADDRESS_MIRROR; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_POINT_MIRROR]); - + samplerDesc.Filter = FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = TEXTURE_ADDRESS_WRAP; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_POINT_WRAP]); - - + + samplerDesc.Filter = FILTER_MIN_MAG_MIP_POINT; samplerDesc.AddressU = TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV = TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW = TEXTURE_ADDRESS_CLAMP; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_POINT_CLAMP]); - + samplerDesc.Filter = FILTER_ANISOTROPIC; samplerDesc.AddressU = TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV = TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressW = TEXTURE_ADDRESS_CLAMP; samplerDesc.MaxAnisotropy = 16; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_ANISO_CLAMP]); - + samplerDesc.Filter = FILTER_ANISOTROPIC; samplerDesc.AddressU = TEXTURE_ADDRESS_WRAP; samplerDesc.AddressV = TEXTURE_ADDRESS_WRAP; samplerDesc.AddressW = TEXTURE_ADDRESS_WRAP; samplerDesc.MaxAnisotropy = 16; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_ANISO_WRAP]); - + samplerDesc.Filter = FILTER_ANISOTROPIC; samplerDesc.AddressU = TEXTURE_ADDRESS_MIRROR; samplerDesc.AddressV = TEXTURE_ADDRESS_MIRROR; @@ -2321,7 +2824,7 @@ void SetUpStates() samplerDesc.MaxAnisotropy = 16; GetDevice()->CreateSamplerState(&samplerDesc, samplers[SSLOT_OBJECTSHADER]); - ZeroMemory( &samplerDesc, sizeof(SamplerDesc) ); + ZeroMemory(&samplerDesc, sizeof(SamplerDesc)); samplerDesc.Filter = FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; samplerDesc.AddressU = TEXTURE_ADDRESS_CLAMP; samplerDesc.AddressV = TEXTURE_ADDRESS_CLAMP; @@ -2356,96 +2859,96 @@ void SetUpStates() { rasterizers[i] = new RasterizerState; } - + RasterizerStateDesc rs; - rs.FillMode=FILL_SOLID; - rs.CullMode=CULL_BACK; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; - rs.SlopeScaledDepthBias=0; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; - rs.AntialiasedLineEnable=false; + rs.FillMode = FILL_SOLID; + rs.CullMode = CULL_BACK; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; + rs.SlopeScaledDepthBias = 0; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; + rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; - GetDevice()->CreateRasterizerState(&rs,rasterizers[RSTYPE_FRONT]); + GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_FRONT]); - - rs.FillMode=FILL_SOLID; - rs.CullMode=CULL_BACK; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; + + rs.FillMode = FILL_SOLID; + rs.CullMode = CULL_BACK; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; rs.SlopeScaledDepthBias = -2.0f; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; - rs.AntialiasedLineEnable=false; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; + rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; - GetDevice()->CreateRasterizerState(&rs,rasterizers[RSTYPE_SHADOW]); + GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_SHADOW]); - rs.FillMode=FILL_SOLID; - rs.CullMode=CULL_NONE; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; + rs.FillMode = FILL_SOLID; + rs.CullMode = CULL_NONE; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; rs.SlopeScaledDepthBias = -2.0f; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; - rs.AntialiasedLineEnable=false; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; + rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; - GetDevice()->CreateRasterizerState(&rs,rasterizers[RSTYPE_SHADOW_DOUBLESIDED]); + GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_SHADOW_DOUBLESIDED]); - rs.FillMode=FILL_WIREFRAME; - rs.CullMode=CULL_BACK; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; - rs.SlopeScaledDepthBias=0; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; + rs.FillMode = FILL_WIREFRAME; + rs.CullMode = CULL_BACK; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; + rs.SlopeScaledDepthBias = 0; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_WIRE]); rs.AntialiasedLineEnable = true; GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_WIRE_SMOOTH]); - - rs.FillMode=FILL_SOLID; - rs.CullMode=CULL_NONE; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; - rs.SlopeScaledDepthBias=0; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; - rs.AntialiasedLineEnable=false; - rs.ConservativeRasterizationEnable = false; - GetDevice()->CreateRasterizerState(&rs,rasterizers[RSTYPE_DOUBLESIDED]); - - rs.FillMode=FILL_WIREFRAME; - rs.CullMode=CULL_NONE; - rs.FrontCounterClockwise=true; + + rs.FillMode = FILL_SOLID; + rs.CullMode = CULL_NONE; + rs.FrontCounterClockwise = true; rs.DepthBias = 0; rs.DepthBiasClamp = 0; - rs.SlopeScaledDepthBias=0; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; + rs.SlopeScaledDepthBias = 0; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; + rs.AntialiasedLineEnable = false; + rs.ConservativeRasterizationEnable = false; + GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_DOUBLESIDED]); + + rs.FillMode = FILL_WIREFRAME; + rs.CullMode = CULL_NONE; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; + rs.SlopeScaledDepthBias = 0; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_WIRE_DOUBLESIDED]); rs.AntialiasedLineEnable = true; GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_WIRE_DOUBLESIDED_SMOOTH]); - - rs.FillMode=FILL_SOLID; - rs.CullMode=CULL_FRONT; - rs.FrontCounterClockwise=true; - rs.DepthBias=0; - rs.DepthBiasClamp=0; - rs.SlopeScaledDepthBias=0; - rs.DepthClipEnable=true; - rs.MultisampleEnable=false; - rs.AntialiasedLineEnable=false; + + rs.FillMode = FILL_SOLID; + rs.CullMode = CULL_FRONT; + rs.FrontCounterClockwise = true; + rs.DepthBias = 0; + rs.DepthBiasClamp = 0; + rs.SlopeScaledDepthBias = 0; + rs.DepthClipEnable = true; + rs.MultisampleEnable = false; + rs.AntialiasedLineEnable = false; rs.ConservativeRasterizationEnable = false; - GetDevice()->CreateRasterizerState(&rs,rasterizers[RSTYPE_BACK]); + GetDevice()->CreateRasterizerState(&rs, rasterizers[RSTYPE_BACK]); rs.FillMode = FILL_SOLID; rs.CullMode = CULL_FRONT; @@ -2588,7 +3091,7 @@ void SetUpStates() GetDevice()->CreateDepthStencilState(&dsd, depthStencils[DSSTYPE_DEPTHREAD]); dsd.DepthEnable = false; - dsd.StencilEnable=false; + dsd.StencilEnable = false; GetDevice()->CreateDepthStencilState(&dsd, depthStencils[DSSTYPE_XRAY]); @@ -2608,10 +3111,10 @@ void SetUpStates() { blendStates[i] = new BlendState; } - + BlendStateDesc bd; ZeroMemory(&bd, sizeof(bd)); - bd.RenderTarget[0].BlendEnable=false; + bd.RenderTarget[0].BlendEnable = false; bd.RenderTarget[0].SrcBlend = BLEND_SRC_ALPHA; bd.RenderTarget[0].DestBlend = BLEND_INV_SRC_ALPHA; bd.RenderTarget[0].BlendOp = BLEND_OP_MAX; @@ -2619,9 +3122,9 @@ void SetUpStates() bd.RenderTarget[0].DestBlendAlpha = BLEND_ZERO; bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL; - bd.AlphaToCoverageEnable=false; + bd.AlphaToCoverageEnable = false; bd.IndependentBlendEnable = false; - GetDevice()->CreateBlendState(&bd,blendStates[BSTYPE_OPAQUE]); + GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_OPAQUE]); bd.RenderTarget[0].SrcBlend = BLEND_SRC_ALPHA; bd.RenderTarget[0].DestBlend = BLEND_INV_SRC_ALPHA; @@ -2629,14 +3132,14 @@ void SetUpStates() bd.RenderTarget[0].SrcBlendAlpha = BLEND_ONE; bd.RenderTarget[0].DestBlendAlpha = BLEND_ONE; bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD; - bd.RenderTarget[0].BlendEnable=true; + bd.RenderTarget[0].BlendEnable = true; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL; bd.AlphaToCoverageEnable = false; bd.IndependentBlendEnable = false; - GetDevice()->CreateBlendState(&bd,blendStates[BSTYPE_TRANSPARENT]); + GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_TRANSPARENT]); - bd.RenderTarget[0].BlendEnable=true; + bd.RenderTarget[0].BlendEnable = true; bd.RenderTarget[0].SrcBlend = BLEND_SRC_ALPHA; bd.RenderTarget[0].DestBlend = BLEND_ONE; bd.RenderTarget[0].BlendOp = BLEND_OP_ADD; @@ -2644,19 +3147,19 @@ void SetUpStates() bd.RenderTarget[0].DestBlendAlpha = BLEND_ONE; bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL; - bd.IndependentBlendEnable=false, - bd.AlphaToCoverageEnable=false; - GetDevice()->CreateBlendState(&bd,blendStates[BSTYPE_ADDITIVE]); + bd.IndependentBlendEnable = false, + bd.AlphaToCoverageEnable = false; + GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_ADDITIVE]); bd.RenderTarget[0].BlendEnable = false; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_DISABLE; bd.IndependentBlendEnable = false, - bd.AlphaToCoverageEnable = false; + bd.AlphaToCoverageEnable = false; GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_COLORWRITEDISABLE]); - bd.RenderTarget[0].BlendEnable=true; + bd.RenderTarget[0].BlendEnable = true; bd.RenderTarget[0].SrcBlend = BLEND_ONE; bd.RenderTarget[0].DestBlend = BLEND_ONE; bd.RenderTarget[0].BlendOp = BLEND_OP_ADD; @@ -2664,9 +3167,9 @@ void SetUpStates() bd.RenderTarget[0].DestBlendAlpha = BLEND_ONE; bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_RED | COLOR_WRITE_ENABLE_GREEN | COLOR_WRITE_ENABLE_BLUE; // alpha is not written by deferred lights! - bd.IndependentBlendEnable=false, - bd.AlphaToCoverageEnable=false; - GetDevice()->CreateBlendState(&bd,blendStates[BSTYPE_DEFERREDLIGHT]); + bd.IndependentBlendEnable = false, + bd.AlphaToCoverageEnable = false; + GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_DEFERREDLIGHT]); bd.RenderTarget[0].BlendEnable = true; bd.RenderTarget[0].SrcBlend = BLEND_ONE; @@ -2677,7 +3180,7 @@ void SetUpStates() bd.RenderTarget[0].BlendOpAlpha = BLEND_OP_ADD; bd.RenderTarget[0].RenderTargetWriteMask = COLOR_WRITE_ENABLE_ALL; bd.IndependentBlendEnable = false, - bd.AlphaToCoverageEnable = false; + bd.AlphaToCoverageEnable = false; GetDevice()->CreateBlendState(&bd, blendStates[BSTYPE_ENVIRONMENTALLIGHT]); bd.RenderTarget[0].SrcBlend = BLEND_INV_SRC_COLOR; @@ -2735,7 +3238,6 @@ void SetUpStates() } - void FixedUpdate() { } @@ -2778,7 +3280,7 @@ void UpdatePerFrameData(float dt) culling.frustum = camera->frustum; } - // Cull objects for every camera: + // Cull objects for each camera: for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; @@ -2789,22 +3291,6 @@ void UpdatePerFrameData(float dt) Entity entity = scene.objects.GetEntity(i); culling.culledObjects.push_back(entity); - if (object.GetRenderTypes() & RENDERTYPE_OPAQUE) - { - //culling.culledRenderer_opaque[object.meshID].push_back(entity); - RenderBatch* batch = (RenderBatch*)frameAllocators[GRAPHICSTHREAD_IMMEDIATE].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = entity; - culling.culledRenderer_opaque.add(batch); - } - if (object.GetRenderTypes() & RENDERTYPE_TRANSPARENT) - { - //culling.culledRenderer_transparent[object.meshID].push_back(entity); - RenderBatch* batch = (RenderBatch*)frameAllocators[GRAPHICSTHREAD_IMMEDIATE].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = entity; - culling.culledRenderer_transparent.add(batch); - } if (object.GetRenderTypes() & RENDERTYPE_WATER) { requestReflectionRendering = true; @@ -3541,6 +4027,7 @@ void DrawWaterRipples(GRAPHICSTHREAD threadID) } + void DrawSoftParticles(const CameraComponent& camera, bool distortion, GRAPHICSTHREAD threadID) { Scene& scene = GetScene(); @@ -4065,7 +4552,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) GetDevice()->EventBegin("ShadowMap Render", threadID); wiProfiler::GetInstance().BeginRange("Shadow Rendering", wiProfiler::DOMAIN_GPU, threadID); - const bool all_layers = layerMask == 0xFFFFFFFF; // this can avoid the recursive call per object : GetLayerMask() + const bool all_layers = layerMask == 0xFFFFFFFF; const FrameCulling& culling = frameCullings[&GetCamera()]; const auto& culledLights = culling.culledLights; @@ -4145,7 +4632,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) AABB boundingbox; boundingbox.createFromHalfWidth(XMFLOAT3(0, 0, 0), XMFLOAT3(siz, siz, f)); - CulledCollection culledRenderer; + RenderQueue renderQueue; bool transparentShadowsRequested = false; for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { @@ -4159,11 +4646,10 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) const LayerComponent& layer = *scene.layers.GetComponent(cullable_entity); if (all_layers || (layerMask & layer.GetLayerMask())) { - //culledRenderer[object.meshID].push_back(cullable_entity); RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = cullable_entity; - culledRenderer.add(batch); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, i, 0); + renderQueue.add(batch); if (object.GetRenderTypes() & RENDERTYPE_TRANSPARENT || object.GetRenderTypes() & RENDERTYPE_WATER) { @@ -4173,7 +4659,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) } } } - if (!culledRenderer.empty()) + if (!renderQueue.empty()) { CameraCB cb; XMStoreFloat4x4(&cb.g_xCamera_VP, light.shadowCam_dirLight[cascade].getVP()); @@ -4186,7 +4672,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) // render opaque shadowmap: GetDevice()->BindRenderTargets(0, nullptr, shadowMapArray_2D, threadID, light.shadowMap_index + cascade); - RenderMeshes(light.shadowCam_dirLight[cascade].Eye, culledRenderer, SHADERTYPE_SHADOW, RENDERTYPE_OPAQUE, threadID); + RenderMeshes(light.shadowCam_dirLight[cascade].Eye, renderQueue, SHADERTYPE_SHADOW, RENDERTYPE_OPAQUE, threadID); if (GetTransparentShadowsEnabled() && transparentShadowsRequested) { @@ -4195,7 +4681,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) shadowMapArray_Transparent }; GetDevice()->BindRenderTargets(ARRAYSIZE(rts), rts, shadowMapArray_2D, threadID, light.shadowMap_index + cascade); - RenderMeshes(light.shadowCam_dirLight[cascade].Eye, culledRenderer, SHADERTYPE_SHADOW, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID); + RenderMeshes(light.shadowCam_dirLight[cascade].Eye, renderQueue, SHADERTYPE_SHADOW, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID); } } @@ -4211,7 +4697,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) Frustum frustum; frustum.ConstructFrustum(light.shadowCam_spotLight[0].farplane, light.shadowCam_spotLight[0].realProjection, light.shadowCam_spotLight[0].View); - CulledCollection culledRenderer; + RenderQueue renderQueue; bool transparentShadowsRequested = false; for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { @@ -4225,11 +4711,10 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) const LayerComponent& layer = *scene.layers.GetComponent(cullable_entity); if (all_layers || (layerMask & layer.GetLayerMask())) { - //culledRenderer[object.meshID].push_back(cullable_entity); RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = cullable_entity; - culledRenderer.add(batch); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, i, 0); + renderQueue.add(batch); if (object.GetRenderTypes() & RENDERTYPE_TRANSPARENT || object.GetRenderTypes() & RENDERTYPE_WATER) { @@ -4239,7 +4724,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) } } } - if (!culledRenderer.empty()) + if (!renderQueue.empty()) { CameraCB cb; XMStoreFloat4x4(&cb.g_xCamera_VP, light.shadowCam_spotLight[0].getVP()); @@ -4252,7 +4737,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) // render opaque shadowmap: GetDevice()->BindRenderTargets(0, nullptr, shadowMapArray_2D, threadID, light.shadowMap_index); - RenderMeshes(frustum.getCamPos(), culledRenderer, SHADERTYPE_SHADOW, RENDERTYPE_OPAQUE, threadID); + RenderMeshes(frustum.getCamPos(), renderQueue, SHADERTYPE_SHADOW, RENDERTYPE_OPAQUE, threadID); if (GetTransparentShadowsEnabled() && transparentShadowsRequested) { @@ -4261,7 +4746,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) shadowMapArray_Transparent }; GetDevice()->BindRenderTargets(ARRAYSIZE(rts), rts, shadowMapArray_2D, threadID, light.shadowMap_index); - RenderMeshes(frustum.getCamPos(), culledRenderer, SHADERTYPE_SHADOW, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID); + RenderMeshes(frustum.getCamPos(), renderQueue, SHADERTYPE_SHADOW, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID); } } @@ -4277,7 +4762,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) break; shadowCounter_Cube++; // shadow indices are already complete so a shadow slot is consumed here even if no rendering actually happens! - CulledCollection culledRenderer; + RenderQueue renderQueue; for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; @@ -4290,16 +4775,15 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) const LayerComponent& layer = *scene.layers.GetComponent(cullable_entity); if (all_layers || (layerMask & layer.GetLayerMask())) { - //culledRenderer[object.meshID].push_back(cullable_entity); RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = cullable_entity; - culledRenderer.add(batch); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, i, 0); + renderQueue.add(batch); } } } } - if (!culledRenderer.empty()) + if (!renderQueue.empty()) { GetDevice()->BindRenderTargets(0, nullptr, shadowMapArray_Cube, threadID, light.shadowMap_index); GetDevice()->ClearDepthStencil(shadowMapArray_Cube, CLEAR_DEPTH, 0.0f, 0, threadID, light.shadowMap_index); @@ -4316,7 +4800,7 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) GetDevice()->UpdateBuffer(constantBuffers[CBTYPE_CUBEMAPRENDER], &cb, threadID); - RenderMeshes(light.position, culledRenderer, SHADERTYPE_SHADOWCUBE, RENDERTYPE_OPAQUE, threadID); + RenderMeshes(light.position, renderQueue, SHADERTYPE_SHADOWCUBE, RENDERTYPE_OPAQUE, threadID); } } @@ -4342,454 +4826,9 @@ void DrawForShadowMap(GRAPHICSTHREAD threadID, uint32_t layerMask) } } -void RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culledRenderer, SHADERTYPE shaderType, UINT renderTypeFlags, GRAPHICSTHREAD threadID, - bool tessellation, bool occlusionCulling, uint32_t layerMask) -{ - // Intensive section, refactor and optimize! - - if (!culledRenderer.empty()) - { - GraphicsDevice* device = GetDevice(); - Scene& scene = GetScene(); - - device->EventBegin("RenderMeshes", threadID); - - tessellation = tessellation && device->CheckCapability(GraphicsDevice::GRAPHICSDEVICE_CAPABILITY_TESSELLATION); - - const XMFLOAT4X4 __identityMat = XMFLOAT4X4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - - struct InstBuf - { - Instance instance; - InstancePrev instancePrev; - }; - - const bool advancedVBRequest = - !IsWireRender() && - (shaderType == SHADERTYPE_FORWARD || - shaderType == SHADERTYPE_DEFERRED || - shaderType == SHADERTYPE_TILEDFORWARD); - - const bool easyTextureBind = - shaderType == SHADERTYPE_TEXTURE || - shaderType == SHADERTYPE_SHADOW || - shaderType == SHADERTYPE_SHADOWCUBE || - shaderType == SHADERTYPE_DEPTHONLY || - shaderType == SHADERTYPE_VOXELIZE; - - const bool all_layers = layerMask == 0xFFFFFFFF; // this can avoid the recursive call per object : GetLayerMask() - - GraphicsPSO* impostorRequest = GetImpostorPSO(shaderType); - - // Render impostors: - if (impostorRequest != nullptr) - { - bool impostorGraphicsStateComplete = false; - - for (size_t batchID = 0; batchID < culledRenderer.dataCount; ++batchID) - { - const RenderBatch& batch = ((RenderBatch*)culledRenderer.dataBegin)[batchID]; - - Entity meshEntity = batch.meshID; - MeshComponent& mesh = *scene.meshes.GetComponent(meshEntity); - if (!mesh.IsRenderable() || !mesh.HasImpostor() /*|| !(mesh.GetRenderTypes() & renderTypeFlags)*/) - { - continue; - } - - //const auto& visibleInstances = iter->second; - - UINT instancesOffset; - size_t alloc_size = /*visibleInstances.size()*/ 1; - alloc_size *= advancedVBRequest ? sizeof(InstBuf) : sizeof(Instance); - void* instances = device->AllocateFromRingBuffer(dynamicVertexBufferPool, alloc_size, instancesOffset, threadID); - - int k = 0; - for (size_t instanceID = 0; instanceID < 1; ++instanceID) - { - Entity objectEntity = batch.instanceID; - - const ObjectComponent& instance = *scene.objects.GetComponent(objectEntity); - if (occlusionCulling && instance.IsOccluded()) - continue; - - const LayerComponent& layer = *scene.layers.GetComponent(objectEntity); - - if (all_layers || (layerMask & layer.GetLayerMask())) - { - const AABB& aabb = *scene.aabb_objects.GetComponent(objectEntity); - - const float impostorThreshold = aabb.getRadius(); - float dist = wiMath::Distance(eye, aabb.getCenter()); - float dither = instance.GetTransparency(); - dither = wiMath::SmoothStep(1.0f, dither, wiMath::Clamp((dist - mesh.impostorDistance) / impostorThreshold, 0, 1)); - if (dither > 1.0f - FLT_EPSILON) - continue; - - XMMATRIX boxMat = mesh.aabb.getAsBoxMatrix(); - - const TransformComponent& transform = *scene.transforms.GetComponent(objectEntity); - - XMFLOAT4X4 tempMat; - XMStoreFloat4x4(&tempMat, boxMat*XMLoadFloat4x4(&transform.world)); - - if (advancedVBRequest) - { - ((volatile InstBuf*)instances)[k].instance.Create(tempMat, instance.color, dither); - - const PreviousFrameTransformComponent& prev_transform = *scene.prev_transforms.GetComponent(objectEntity); - XMStoreFloat4x4(&tempMat, boxMat*XMLoadFloat4x4(&prev_transform.world_prev)); - ((volatile InstBuf*)instances)[k].instancePrev.Create(tempMat); - } - else - { - ((volatile Instance*)instances)[k].Create(tempMat, instance.color, dither); - } - - ++k; - } - } - - device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); - - if (k < 1) - continue; - - if (!advancedVBRequest || IsWireRender()) - { - GPUBuffer* vbs[] = { - &impostorVB_POS, - &impostorVB_TEX, - dynamicVertexBufferPool - }; - UINT strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(Instance) - }; - UINT offsets[] = { - 0, - 0, - instancesOffset - }; - device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - } - else - { - GPUBuffer* vbs[] = { - &impostorVB_POS, - &impostorVB_TEX, - &impostorVB_POS, - dynamicVertexBufferPool - }; - UINT strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_POS), - sizeof(InstBuf) - }; - UINT offsets[] = { - 0, - 0, - 0, - instancesOffset - }; - device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - } - - GPUResource* res[] = { - mesh.impostorTarget.GetTexture(0), - mesh.impostorTarget.GetTexture(1), - mesh.impostorTarget.GetTexture(2) - }; - device->BindResources(PS, res, TEXSLOT_ONDEMAND0, (easyTextureBind ? 1 : ARRAYSIZE(res)), threadID); - - if (!impostorGraphicsStateComplete) - { - device->BindGraphicsPSO(impostorRequest, threadID); - device->BindConstantBuffer(PS, &impostorMaterialCB, CB_GETBINDSLOT(MaterialCB), threadID); - SetAlphaRef(0.75f, threadID); - impostorGraphicsStateComplete = true; - } - - device->DrawInstanced(6 * 6, k, 0, 0, threadID); // 6 * 6: see MeshComponent::CreateImpostorVB function - - } - } - - - PRIMITIVETOPOLOGY prevTOPOLOGY = TRIANGLELIST; - - // Render meshes: - for (size_t batchID = 0; batchID < culledRenderer.dataCount; ++batchID) - { - const RenderBatch& batch = ((RenderBatch*)culledRenderer.dataBegin)[batchID]; - - Entity meshEntity = batch.meshID; - MeshComponent& mesh = *scene.meshes.GetComponent(meshEntity); - if (!mesh.IsRenderable() /*|| !(mesh.GetRenderTypes() & renderTypeFlags)*/) - { - continue; - } - - //const auto& visibleInstances = iter->second; - - const float tessF = mesh.GetTessellationFactor(); - const bool tessellatorRequested = tessF > 0 && tessellation; - - if (tessellatorRequested) - { - TessellationCB tessCB; - tessCB.g_f4TessFactors = XMFLOAT4(tessF, tessF, tessF, tessF); - device->UpdateBuffer(constantBuffers[CBTYPE_TESSELLATION], &tessCB, threadID); - device->BindConstantBuffer(HS, constantBuffers[CBTYPE_TESSELLATION], CBSLOT_RENDERER_TESSELLATION, threadID); - } - - bool forceAlphaTestForDithering = false; - - UINT instancesOffset; - size_t alloc_size = /*visibleInstances.size()*/1; - alloc_size *= advancedVBRequest ? sizeof(InstBuf) : sizeof(Instance); - void* instances = device->AllocateFromRingBuffer(dynamicVertexBufferPool, alloc_size, instancesOffset, threadID); - - int k = 0; - for (size_t instanceID = 0; instanceID < 1; ++instanceID) - { - Entity objectEntity = batch.instanceID; - - const ObjectComponent& instance = *scene.objects.GetComponent(objectEntity); - if (occlusionCulling && instance.IsOccluded()) - continue; - - const LayerComponent& layer = *scene.layers.GetComponent(objectEntity); - - if (all_layers || (layerMask & layer.GetLayerMask())) - { - float dither = instance.GetTransparency(); - if (impostorRequest != nullptr) - { - // fade out to impostor... - const AABB& aabb = *scene.aabb_objects.GetComponent(objectEntity); - const float impostorThreshold = aabb.getRadius(); - float dist = wiMath::Distance(eye, aabb.getCenter()); - if (mesh.HasImpostor()) - dither = wiMath::SmoothStep(dither, 1.0f, wiMath::Clamp((dist - impostorThreshold - mesh.impostorDistance) / impostorThreshold, 0, 1)); - } - if (dither > 1.0f - FLT_EPSILON) - continue; - - forceAlphaTestForDithering = forceAlphaTestForDithering || (dither > 0); - - const TransformComponent& transform = *scene.transforms.GetComponent(objectEntity); - - if (advancedVBRequest || tessellatorRequested) - { - ((volatile InstBuf*)instances)[k].instance.Create(transform.world, instance.color); - - const PreviousFrameTransformComponent& prev_transform = *scene.prev_transforms.GetComponent(objectEntity); - ((volatile InstBuf*)instances)[k].instancePrev.Create(prev_transform.world_prev); - } - else - { - ((volatile Instance*)instances)[k].Create(transform.world, instance.color, dither); - } - - ++k; - } - } - - device->InvalidateBufferAccess(dynamicVertexBufferPool, threadID); - - if (k < 1) - continue; - - device->BindIndexBuffer(mesh.indexBuffer.get(), mesh.GetIndexFormat(), 0, threadID); - - enum class BOUNDVERTEXBUFFERTYPE - { - NOTHING, - POSITION, - POSITION_TEXCOORD, - EVERYTHING, - }; - BOUNDVERTEXBUFFERTYPE boundVBType_Prev = BOUNDVERTEXBUFFERTYPE::NOTHING; - - for (MeshComponent::MeshSubset& subset : mesh.subsets) - { - if (subset.indexCount == 0) - { - continue; - } - const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); - - GraphicsPSO* pso = /*material.customShader == nullptr ?*/ GetObjectPSO(shaderType, mesh.IsDoubleSided(), tessellatorRequested, material, forceAlphaTestForDithering) /*: material.customShader->passes[shaderType].pso*/; - if (pso == nullptr) - { - continue; - } - - bool subsetRenderable = false; - - if (renderTypeFlags & RENDERTYPE_OPAQUE) - { - subsetRenderable = subsetRenderable || (!material.IsTransparent() && !material.IsWater()); - } - if (renderTypeFlags & RENDERTYPE_TRANSPARENT) - { - subsetRenderable = subsetRenderable || material.IsTransparent(); - } - if (renderTypeFlags & RENDERTYPE_WATER) - { - subsetRenderable = subsetRenderable || material.IsWater(); - } - if (shaderType == SHADERTYPE_SHADOW || shaderType == SHADERTYPE_SHADOWCUBE) - { - subsetRenderable = subsetRenderable && material.IsCastingShadow(); - } - - if (!subsetRenderable) - { - continue; - } - - BOUNDVERTEXBUFFERTYPE boundVBType; - if (advancedVBRequest || tessellatorRequested) - { - boundVBType = BOUNDVERTEXBUFFERTYPE::EVERYTHING; - } - else - { - // simple vertex buffers are used in some passes (note: tessellator requires more attributes) - if ((shaderType == SHADERTYPE_DEPTHONLY || shaderType == SHADERTYPE_SHADOW || shaderType == SHADERTYPE_SHADOWCUBE) && !material.IsAlphaTestEnabled() && !forceAlphaTestForDithering) - { - if (shaderType == SHADERTYPE_SHADOW && material.IsTransparent()) - { - boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; - } - else - { - // bypass texcoord stream for non alphatested shadows and zprepass - boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION; - } - } - else - { - boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; - } - } - - if (material.IsWater()) - { - boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; - } - - if (IsWireRender()) - { - boundVBType = BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD; - } - - // Only bind vertex buffers when the layout changes - if (boundVBType != boundVBType_Prev) - { - // Assemble the required vertex buffer: - switch (boundVBType) - { - case BOUNDVERTEXBUFFERTYPE::POSITION: - { - GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), - dynamicVertexBufferPool - }; - UINT strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(Instance) - }; - UINT offsets[] = { - 0, - instancesOffset - }; - device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - } - break; - case BOUNDVERTEXBUFFERTYPE::POSITION_TEXCOORD: - { - GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), - mesh.vertexBuffer_TEX.get(), - dynamicVertexBufferPool - }; - UINT strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(Instance) - }; - UINT offsets[] = { - 0, - 0, - instancesOffset - }; - device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - } - break; - case BOUNDVERTEXBUFFERTYPE::EVERYTHING: - { - GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.get() != nullptr ? mesh.streamoutBuffer_POS.get() : mesh.vertexBuffer_POS.get(), - mesh.vertexBuffer_TEX.get(), - mesh.streamoutBuffer_PRE.get() != nullptr ? mesh.streamoutBuffer_PRE.get() : mesh.vertexBuffer_POS.get(), - dynamicVertexBufferPool - }; - UINT strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_POS), - sizeof(InstBuf) - }; - UINT offsets[] = { - 0, - 0, - 0, - instancesOffset - }; - device->BindVertexBuffers(vbs, 0, ARRAYSIZE(vbs), strides, offsets, threadID); - } - break; - default: - assert(0); - break; - } - } - boundVBType_Prev = boundVBType; - - device->BindConstantBuffer(PS, material.constantBuffer.get(), CB_GETBINDSLOT(MaterialCB), threadID); - - device->BindStencilRef(material.GetStencilRef(), threadID); - - device->BindGraphicsPSO(pso, threadID); - - GPUResource* res[] = { - material.GetBaseColorMap(), - material.GetNormalMap(), - material.GetSurfaceMap(), - material.GetDisplacementMap(), - }; - device->BindResources(PS, res, TEXSLOT_ONDEMAND0, (easyTextureBind ? 2 : ARRAYSIZE(res)), threadID); - - SetAlphaRef(material.alphaRef, threadID); - - device->DrawIndexedInstanced((int)subset.indexCount, k, subset.indexOffset, 0, 0, threadID); - } - - } - - ResetAlphaRef(threadID); - - device->EventEnd(threadID); - } -} - void DrawWorld(const CameraComponent& camera, bool tessellation, GRAPHICSTHREAD threadID, SHADERTYPE shaderType, bool grass, bool occlusionCulling, uint32_t layerMask) { + Scene& scene = GetScene(); const FrameCulling& culling = frameCullings[&camera]; GetDevice()->EventBegin("DrawWorld", threadID); @@ -4807,8 +4846,6 @@ void DrawWorld(const CameraComponent& camera, bool tessellation, GRAPHICSTHREAD SetAlphaRef(0.25f, threadID); } - Scene& scene = GetScene(); - for (size_t i = 0; i < scene.hairs.GetCount(); ++i) { const wiHairParticle& hair = scene.hairs[i]; @@ -4823,9 +4860,34 @@ void DrawWorld(const CameraComponent& camera, bool tessellation, GRAPHICSTHREAD } } - if (!culling.culledRenderer_opaque.empty()/* || (grass && culling.culledHairParticleSystems.empty())*/) + + RenderQueue renderQueue; + for (Entity entity : culling.culledObjects) { - RenderMeshes(camera.Eye, culling.culledRenderer_opaque, shaderType, RENDERTYPE_OPAQUE, threadID, tessellation, GetOcclusionCullingEnabled() && occlusionCulling, layerMask); + if (layerMask != ~0) + { + const LayerComponent& layer = *scene.layers.GetComponent(entity); + if (!(layer.GetLayerMask() & layerMask)) + { + continue; + } + } + + size_t instanceIndex = scene.objects.GetIndex(entity); + const ObjectComponent& object = scene.objects[instanceIndex]; + + if (object.GetRenderTypes() & RENDERTYPE_OPAQUE) + { + RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, instanceIndex, wiMath::DistanceEstimated(camera.Eye, object.position)); + renderQueue.add(batch); + } + } + if (!renderQueue.empty()) + { + renderQueue.sort(RenderQueue::SORT_FRONT_TO_BACK); + RenderMeshes(camera.Eye, renderQueue, shaderType, RENDERTYPE_OPAQUE, threadID, tessellation, GetOcclusionCullingEnabled() && occlusionCulling); } GetDevice()->EventEnd(threadID); @@ -4834,6 +4896,7 @@ void DrawWorld(const CameraComponent& camera, bool tessellation, GRAPHICSTHREAD void DrawWorldTransparent(const CameraComponent& camera, SHADERTYPE shaderType, GRAPHICSTHREAD threadID, bool grass, bool occlusionCulling, uint32_t layerMask) { + Scene& scene = GetScene(); const FrameCulling& culling = frameCullings[&camera]; GetDevice()->EventBegin("DrawWorldTransparent", threadID); @@ -4851,7 +4914,6 @@ void DrawWorldTransparent(const CameraComponent& camera, SHADERTYPE shaderType, if (grass && GetAlphaCompositionEnabled()) { // transparent passes can only render hair when alpha composition is enabled - Scene& scene = GetScene(); for (size_t i = 0; i < scene.hairs.GetCount(); ++i) { @@ -4867,9 +4929,33 @@ void DrawWorldTransparent(const CameraComponent& camera, SHADERTYPE shaderType, } } - if (!culling.culledRenderer_transparent.empty()) + RenderQueue renderQueue; + for (Entity entity : culling.culledObjects) { - RenderMeshes(camera.Eye, culling.culledRenderer_transparent, shaderType, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID, false, GetOcclusionCullingEnabled() && occlusionCulling, layerMask); + if (layerMask != ~0) + { + const LayerComponent& layer = *scene.layers.GetComponent(entity); + if (!(layer.GetLayerMask() & layerMask)) + { + continue; + } + } + + size_t instanceIndex = scene.objects.GetIndex(entity); + const ObjectComponent& object = scene.objects[instanceIndex]; + + if (object.GetRenderTypes() & RENDERTYPE_TRANSPARENT) + { + RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, instanceIndex, wiMath::DistanceEstimated(camera.Eye, object.position)); + renderQueue.add(batch); + } + } + if (!renderQueue.empty()) + { + renderQueue.sort(RenderQueue::SORT_BACK_TO_FRONT); + RenderMeshes(camera.Eye, renderQueue, shaderType, RENDERTYPE_TRANSPARENT | RENDERTYPE_WATER, threadID, false, GetOcclusionCullingEnabled() && occlusionCulling); } GetDevice()->EventEnd(threadID); @@ -5558,7 +5644,7 @@ void RefreshEnvProbes(GRAPHICSTHREAD threadID) SPHERE culler = SPHERE(center, zFarP); - CulledCollection culledRenderer; + RenderQueue renderQueue; for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; @@ -5569,18 +5655,17 @@ void RefreshEnvProbes(GRAPHICSTHREAD threadID) if ((layerMask & layer.GetLayerMask())) { const ObjectComponent& object = scene.objects[i]; - //culledRenderer[object.meshID].push_back(cullable_entity); RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = cullable_entity; - culledRenderer.add(batch); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, i, 0); + renderQueue.add(batch); } } } - if (!culledRenderer.empty()) + if (!renderQueue.empty()) { - RenderMeshes(center, culledRenderer, SHADERTYPE_ENVMAPCAPTURE, RENDERTYPE_OPAQUE | RENDERTYPE_TRANSPARENT, threadID); + RenderMeshes(center, renderQueue, SHADERTYPE_ENVMAPCAPTURE, RENDERTYPE_OPAQUE | RENDERTYPE_TRANSPARENT, threadID); } // sky @@ -5720,7 +5805,7 @@ void VoxelRadiance(GRAPHICSTHREAD threadID) bbox.createFromHalfWidth(center, extents); - CulledCollection culledRenderer; + RenderQueue renderQueue; for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; @@ -5728,15 +5813,14 @@ void VoxelRadiance(GRAPHICSTHREAD threadID) { Entity cullable_entity = scene.aabb_objects.GetEntity(i); const ObjectComponent& object = scene.objects[i]; - //culledRenderer[object.meshID].push_back(cullable_entity); RenderBatch* batch = (RenderBatch*)frameAllocators[threadID].allocate(sizeof(RenderBatch)); - batch->meshID = object.meshID; - batch->instanceID = cullable_entity; - culledRenderer.add(batch); + size_t meshIndex = scene.meshes.GetIndex(object.meshID); + batch->Create(meshIndex, i, 0); + renderQueue.add(batch); } } - if (!culledRenderer.empty()) + if (!renderQueue.empty()) { ViewPort VP; VP.TopLeftX = 0; @@ -5750,7 +5834,7 @@ void VoxelRadiance(GRAPHICSTHREAD threadID) GPUResource* UAVs[] = { resourceBuffers[RBTYPE_VOXELSCENE] }; device->BindUAVs(PS, UAVs, 0, 1, threadID); - RenderMeshes(center, culledRenderer, SHADERTYPE_VOXELIZE, RENDERTYPE_OPAQUE, threadID); + RenderMeshes(center, renderQueue, SHADERTYPE_VOXELIZE, RENDERTYPE_OPAQUE, threadID); // Copy the packed voxel scene data to a 3D texture, then delete the voxel scene emission data. The cone tracing will operate on the 3D texture device->EventBegin("Voxel Scene Copy - Clear", threadID); diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 8b2924d48..f1e54978b 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -86,18 +86,6 @@ namespace wiRenderer void BindGBufferTextures(wiGraphicsTypes::Texture2D* slot0, wiGraphicsTypes::Texture2D* slot1, wiGraphicsTypes::Texture2D* slot2, wiGraphicsTypes::Texture2D* slot3, wiGraphicsTypes::Texture2D* slot4, GRAPHICSTHREAD threadID); void BindDepthTextures(wiGraphicsTypes::Texture2D* depth, wiGraphicsTypes::Texture2D* linearDepth, GRAPHICSTHREAD threadID); - struct CulledCollection - { - uint8_t* dataBegin = nullptr; - size_t dataCount = 0; - - inline bool empty() const { return dataBegin == nullptr || dataCount == 0; } - inline void clear() { dataBegin = nullptr; dataCount = 0; } - inline void add(void* item) { if (empty()) dataBegin = (uint8_t*)item; dataCount++; } - }; - void RenderMeshes(const XMFLOAT3& eye, const CulledCollection& culledRenderer, SHADERTYPE shaderType, UINT renderTypeFlags, GRAPHICSTHREAD threadID, - bool tessellation = false, bool occlusionCulling = false, uint32_t layerMask = 0xFFFFFFFF); - void DrawSky(GRAPHICSTHREAD threadID); void DrawSun(GRAPHICSTHREAD threadID); void DrawWorld(const wiSceneSystem::CameraComponent& camera, bool tessellation, GRAPHICSTHREAD threadID, SHADERTYPE shaderType, bool grass, bool occlusionCulling, uint32_t layerMask = 0xFFFFFFFF); diff --git a/WickedEngine/wiRenderer_BindLua.cpp b/WickedEngine/wiRenderer_BindLua.cpp index 52e842867..9312a8f28 100644 --- a/WickedEngine/wiRenderer_BindLua.cpp +++ b/WickedEngine/wiRenderer_BindLua.cpp @@ -8,7 +8,6 @@ #include "Texture_BindLua.h" #include "wiEmittedParticle.h" #include "wiHairParticle.h" -#include "wiPHYSICS.h" using namespace std; using namespace wiECS; diff --git a/WickedEngine/wiSceneSystem.cpp b/WickedEngine/wiSceneSystem.cpp index f7919b5fb..3eb596d0b 100644 --- a/WickedEngine/wiSceneSystem.cpp +++ b/WickedEngine/wiSceneSystem.cpp @@ -2,9 +2,8 @@ #include "wiMath.h" #include "wiTextureHelper.h" #include "wiResourceManager.h" -#include "wiPHYSICS.h" +#include "wiPhysicsEngine.h" #include "wiArchive.h" -#include "wiPhysics.h" using namespace wiECS; using namespace wiGraphicsTypes; @@ -1537,6 +1536,8 @@ namespace wiSceneSystem aabb = mesh->aabb.get(transform->world); sceneBounds = AABB::Merge(sceneBounds, aabb); + object.position = transform->GetPosition(); + if (mesh->IsSkinned() || mesh->IsDynamic()) { object.SetDynamic(true); diff --git a/WickedEngine/wiSceneSystem.h b/WickedEngine/wiSceneSystem.h index ba4996a22..beb284035 100644 --- a/WickedEngine/wiSceneSystem.h +++ b/WickedEngine/wiSceneSystem.h @@ -387,6 +387,8 @@ namespace wiSceneSystem // Non-serialized attributes: + XMFLOAT3 position = XMFLOAT3(0, 0, 0); + // occlusion result history bitfield (32 bit->32 frame history) uint32_t occlusionHistory = ~0; // occlusion query pool index