From 521e2ed39c7f3c2e1b1093e40408e15e85bba787 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sat, 14 Sep 2024 04:59:39 +0200 Subject: [PATCH] Run the light tiles compute shader --- .../hwrenderer/data/hw_renderstate.h | 1 + .../hwrenderer/data/hw_viewpointuniforms.h | 2 + .../descriptorsets/vk_descriptorset.cpp | 33 +++++++++++++++++ .../vulkan/descriptorsets/vk_descriptorset.h | 14 ++++++- .../vulkan/pipelines/vk_renderpass.cpp | 18 +++++++++ .../vulkan/pipelines/vk_renderpass.h | 11 ++++++ .../rendering/vulkan/shaders/vk_shader.h | 7 ++++ .../vulkan/textures/vk_renderbuffers.cpp | 4 +- .../rendering/vulkan/vk_renderdevice.cpp | 2 +- .../rendering/vulkan/vk_renderstate.cpp | 37 +++++++++++++++++++ src/common/rendering/vulkan/vk_renderstate.h | 1 + .../hwrenderer/scene/hw_drawinfo.cpp | 2 + .../shaders/scene/binding_rsbuffers.glsl | 2 + .../static/shaders/scene/comp_lighttiles.glsl | 31 +++++++++++++--- wadsrc/static/shaders/scene/frag_main.glsl | 5 +++ .../static/shaders/scene/layout_shared.glsl | 3 +- 16 files changed, 162 insertions(+), 11 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index d5fddf554..3ad41688d 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -699,6 +699,7 @@ public: } // Draw level mesh + virtual void DispatchLightTiles() { } virtual void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) { } virtual int GetNextQueryIndex() { return 0; } virtual void BeginQuery() { } diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h index fed7827fb..89cb6aac0 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointuniforms.h @@ -33,6 +33,8 @@ struct HWViewpointUniforms int mLightBlendMode = 0; + int mLightTilesWidth = 0; + void CalcDependencies() { mNormalViewMatrix.computeNormalMatrix(mViewMatrix); diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index 9a73a3297..4090beed5 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -43,9 +43,11 @@ VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb) CreateLevelMeshLayout(); CreateRSBufferLayout(); CreateFixedLayout(); + CreateLightTilesLayout(); CreateLevelMeshPool(); CreateRSBufferPool(); CreateFixedPool(); + CreateLightTilesPool(); CreateBindlessSet(); } @@ -59,6 +61,7 @@ void VkDescriptorSetManager::Init() { RSBuffer.Set = RSBuffer.Pool->allocate(RSBuffer.Layout.get()); LevelMesh.Set = LevelMesh.Pool->allocate(LevelMesh.Layout.get()); + LightTiles.Set = LightTiles.Pool->allocate(LightTiles.Layout.get()); auto rsbuffers = fb->GetBufferManager()->GetRSBuffers(); WriteDescriptors() @@ -81,6 +84,7 @@ void VkDescriptorSetManager::BeginFrame() { UpdateFixedSet(); UpdateLevelMeshSet(); + UpdateLightTilesSet(); } void VkDescriptorSetManager::UpdateLevelMeshSet() @@ -97,6 +101,15 @@ void VkDescriptorSetManager::UpdateLevelMeshSet() .Execute(fb->GetDevice()); } +void VkDescriptorSetManager::UpdateLightTilesSet() +{ + WriteDescriptors() + .AddStorageImage(LightTiles.Set.get(), 0, fb->GetBuffers()->SceneZMinMax[4].View.get(), VK_IMAGE_LAYOUT_GENERAL) + .AddBuffer(LightTiles.Set.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer()) + .AddBuffer(LightTiles.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBuffers()->SceneLightTiles.get()) + .Execute(fb->GetDevice()); +} + void VkDescriptorSetManager::UpdateFixedSet() { fb->GetCommands()->DrawDeleteList->Add(std::move(Fixed.Set)); @@ -250,6 +263,26 @@ void VkDescriptorSetManager::CreateFixedLayout() Fixed.Layout = builder.Create(fb->GetDevice()); } +void VkDescriptorSetManager::CreateLightTilesLayout() +{ + LightTiles.Layout = DescriptorSetLayoutBuilder() + .AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT) + .AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT) + .AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT) + .DebugName("VkDescriptorSetManager.LightTiles.Layout") + .Create(fb->GetDevice()); +} + +void VkDescriptorSetManager::CreateLightTilesPool() +{ + LightTiles.Pool = DescriptorPoolBuilder() + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1) + .AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2) + .MaxSets(1) + .DebugName("VkDescriptorSetManager.LightTiles.Pool") + .Create(fb->GetDevice()); +} + void VkDescriptorSetManager::CreateLevelMeshPool() { LevelMesh.Pool = DescriptorPoolBuilder() diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h index 90ccbb458..bef21dc79 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h @@ -21,17 +21,18 @@ public: void Deinit(); void BeginFrame(); void ResetHWTextureSets(); - void UpdateLevelMeshSet(); VulkanDescriptorSetLayout* GetLevelMeshLayout() { return LevelMesh.Layout.get(); } VulkanDescriptorSetLayout* GetRSBufferLayout() { return RSBuffer.Layout.get(); } VulkanDescriptorSetLayout* GetFixedLayout() { return Fixed.Layout.get(); } VulkanDescriptorSetLayout* GetBindlessLayout() { return Bindless.Layout.get(); } + VulkanDescriptorSetLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); } VulkanDescriptorSet* GetLevelMeshSet() { return LevelMesh.Set.get(); } VulkanDescriptorSet* GetRSBufferSet() { return RSBuffer.Set.get(); } VulkanDescriptorSet* GetFixedSet() { return Fixed.Set.get(); } VulkanDescriptorSet* GetBindlessSet() { return Bindless.Set.get(); } + VulkanDescriptorSet* GetLightTilesSet() { return LightTiles.Set.get(); } VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray& textures, bool bindShadowMapBuffers); @@ -45,11 +46,15 @@ private: void CreateLevelMeshLayout(); void CreateRSBufferLayout(); void CreateFixedLayout(); + void CreateLightTilesLayout(); void CreateLevelMeshPool(); void CreateRSBufferPool(); void CreateFixedPool(); + void CreateLightTilesPool(); void CreateBindlessSet(); void UpdateFixedSet(); + void UpdateLevelMeshSet(); + void UpdateLightTilesSet(); std::unique_ptr AllocatePPSet(VulkanDescriptorSetLayout* layout); @@ -90,6 +95,13 @@ private: std::unique_ptr Pool; } Postprocess; + struct + { + std::unique_ptr Pool; + std::unique_ptr Set; + std::unique_ptr Layout; + } LightTiles; + std::list Materials; static const int MaxFixedSets = 100; diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp index c5c601761..f7c1a8797 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.cpp @@ -64,6 +64,8 @@ VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb) } PipelineCache = builder.Create(fb->GetDevice()); + + CreateLightTilesPipeline(); } VkRenderPassManager::~VkRenderPassManager() @@ -154,6 +156,22 @@ VkPPRenderPassSetup* VkRenderPassManager::GetPPRenderPass(const VkPPRenderPassKe return passSetup.get(); } +void VkRenderPassManager::CreateLightTilesPipeline() +{ + LightTiles.Layout = PipelineLayoutBuilder() + .AddSetLayout(fb->GetDescriptorSetManager()->GetLightTilesLayout()) + .AddPushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(LightTilesPushConstants)) + .DebugName("VkRenderPassManager.LightTiles.Layout") + .Create(fb->GetDevice()); + + LightTiles.Pipeline = ComputePipelineBuilder() + .Cache(PipelineCache.get()) + .Layout(LightTiles.Layout.get()) + .ComputeShader(fb->GetShaderManager()->GetLightTilesShader()) + .DebugName("VkRenderPassManager.LightTiles.Pipeline") + .Create(fb->GetDevice()); +} + ///////////////////////////////////////////////////////////////////////////// VkRenderPassSetup::VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb) diff --git a/src/common/rendering/vulkan/pipelines/vk_renderpass.h b/src/common/rendering/vulkan/pipelines/vk_renderpass.h index aeba5adb7..0b559650d 100644 --- a/src/common/rendering/vulkan/pipelines/vk_renderpass.h +++ b/src/common/rendering/vulkan/pipelines/vk_renderpass.h @@ -115,7 +115,12 @@ public: VulkanPipelineCache* GetCache() { return PipelineCache.get(); } + VulkanPipelineLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); } + VulkanPipeline* GetLightTilesPipeline() { return LightTiles.Pipeline.get(); } + private: + void CreateLightTilesPipeline(); + VulkanRenderDevice* fb = nullptr; std::map> RenderPassSetup; @@ -124,6 +129,12 @@ private: std::map> PPRenderPassSetup; + struct + { + std::unique_ptr Layout; + std::unique_ptr Pipeline; + } LightTiles; + FString CacheFilename; std::unique_ptr PipelineCache; }; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index 5e2230630..d545f3d7c 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -53,6 +53,13 @@ struct PushConstants int uFogballIndex; // fog balls }; +struct LightTilesPushConstants +{ + int normalLightCount; + int modulatedLightCount; + int subtractiveLightCount; +}; + class VkShaderKey { public: diff --git a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp index a3ccf6946..259e67999 100644 --- a/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/src/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -292,7 +292,7 @@ void VkRenderBuffers::CreateSceneZMinMax(int width, int height) SceneZMinMax[i].Image = ImageBuilder() .Size(width, height) .Format(VK_FORMAT_R32G32_SFLOAT) - .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT) + .Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT) .DebugName("VkRenderBuffers.SceneZMinMax") .Create(fb->GetDevice()); @@ -309,7 +309,7 @@ void VkRenderBuffers::CreateSceneLightTiles(int width, int height) height = (height + 63) / 64; // Make room for 16 lights plus the lightdata header - size_t blockSize = (1 + 3 * 16) * sizeof(FVector4); + size_t blockSize = (1 + 4 * 16) * sizeof(FVector4); SceneLightTiles = BufferBuilder() .Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 873214bb7..770bd4858 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -236,6 +236,7 @@ void VulkanRenderDevice::InitializeState() mPostprocess.reset(new VkPostprocess(this)); mDescriptorSetManager.reset(new VkDescriptorSetManager(this)); + mShaderManager.reset(new VkShaderManager(this)); mRenderPassManager.reset(new VkRenderPassManager(this)); mLevelMesh.reset(new VkLevelMesh(this)); mLightmapper.reset(new VkLightmapper(this)); @@ -245,7 +246,6 @@ void VulkanRenderDevice::InitializeState() mSkyData = new FSkyVertexBuffer(this); mShadowMap = new ShadowMap(this); - mShaderManager.reset(new VkShaderManager(this)); mDescriptorSetManager->Init(); #ifdef __APPLE__ diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 3ee0d446e..c0d48ad73 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -867,6 +867,43 @@ void VkRenderState::ApplyLevelMesh() mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetDrawIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32); } +void VkRenderState::DispatchLightTiles() +{ + EndRenderPass(); + + auto cmdbuffer = fb->GetCommands()->GetDrawCommands(); + + // To do: run the zminmax pass + VkImageTransition() + .AddImage(&fb->GetBuffers()->SceneZMinMax[4], VK_IMAGE_LAYOUT_GENERAL, true /* false */) + .Execute(cmdbuffer); + + PipelineBarrier() + .AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); + + LightTilesPushConstants pushConstants = {}; + //auto mesh = fb->GetLevelMesh()->GetMesh(); + //pushConstants.normalLightCount = mesh->Mesh.NormalLightCount; + //pushConstants.modulatedLightCount = mesh->Mesh.ModulatedLightCount; + //pushConstants.subtractiveLightCount = mesh->Mesh.SubtractiveLightCount; + + auto pipelines = fb->GetRenderPassManager(); + auto descriptors = fb->GetDescriptorSetManager(); + cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipelines->GetLightTilesPipeline()); + cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, pipelines->GetLightTilesLayout(), 0, descriptors->GetLightTilesSet()); + cmdbuffer->pushConstants(pipelines->GetLightTilesLayout(), VK_SHADER_STAGE_COMPUTE_BIT, 0, (uint32_t)sizeof(LightTilesPushConstants), &pushConstants); + + cmdbuffer->dispatch( + (fb->GetBuffers()->GetWidth() + 63) / 64, + (fb->GetBuffers()->GetHeight() + 63) / 64, + 1); + + PipelineBarrier() + .AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(cmdbuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); +} + void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) { ApplyLevelMesh(); diff --git a/src/common/rendering/vulkan/vk_renderstate.h b/src/common/rendering/vulkan/vk_renderstate.h index 76d2efab0..8b59716ca 100644 --- a/src/common/rendering/vulkan/vk_renderstate.h +++ b/src/common/rendering/vulkan/vk_renderstate.h @@ -57,6 +57,7 @@ public: void ResetVertices() override; // Draw level mesh + void DispatchLightTiles() override; void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) override; int GetNextQueryIndex() override; void BeginQuery() override; diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 9d929a962..9d609a5a0 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -114,6 +114,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni VPUniforms.mViewOffsetX = -screen->mSceneViewport.left; VPUniforms.mViewOffsetY = -screen->mSceneViewport.top; VPUniforms.mViewHeight = viewheight; + VPUniforms.mLightTilesWidth = (screen->mScreenViewport.width + 63) / 64; if (lightmode == ELightMode::Build) { VPUniforms.mGlobVis = 1 / 64.f; @@ -442,6 +443,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state) state.SetColorMask(false); state.SetCulling(Cull_CW); state.DrawLevelMesh(LevelMeshDrawType::Opaque, true); + state.DispatchLightTiles(); state.DrawLevelMesh(LevelMeshDrawType::Masked, false); // To do: properly mark wall top/bottom as opaque so we don't need this if (gl_portals) { diff --git a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl index 289385a05..b090d0009 100644 --- a/wadsrc/static/shaders/scene/binding_rsbuffers.glsl +++ b/wadsrc/static/shaders/scene/binding_rsbuffers.glsl @@ -19,6 +19,8 @@ layout(set = 1, binding = 0, std140) uniform ViewpointUBO int uShadowmapFilter; int uLightBlendMode; + + int uLightTilesWidth; // Levelmesh light tiles }; layout(set = 1, binding = 1, std140) uniform MatricesUBO diff --git a/wadsrc/static/shaders/scene/comp_lighttiles.glsl b/wadsrc/static/shaders/scene/comp_lighttiles.glsl index 38dae0930..5dc613c56 100644 --- a/wadsrc/static/shaders/scene/comp_lighttiles.glsl +++ b/wadsrc/static/shaders/scene/comp_lighttiles.glsl @@ -1,12 +1,12 @@ layout(local_size_x = 32, local_size_y = 32) in; -layout(binding = 0, rg32f) readonly uniform image2D zminmax; +layout(set = 0, binding = 0, rg32f) readonly uniform image2D zminmax; -layout(binding = 1) readonly buffer Lights +layout(set = 0, binding = 1) readonly buffer Lights { vec4 lights[]; }; -layout(binding = 1) buffer Tiles +layout(set = 0, binding = 2) buffer Tiles { vec4 tiles[]; }; @@ -26,18 +26,37 @@ void main() return; const int maxLights = 16; - const int lightSize = 3; + const int lightSize = 4; int tileOffset = (tilePos.x + tilePos.y * zminmaxSize.x) * (1 + maxLights * lightSize); vec2 minmax = imageLoad(zminmax, tilePos).xy; float zmin = minmax.x; float zmax = minmax.y; - int tileNormalCount = 0; + int tileNormalCount = 1; int tileModulatedCount = 0; int tileSubtractiveCount = 0; // To do: cull and add lights - tiles[tileOffset] = vec4(ivec4(tileNormalCount, tileModulatedCount, tileSubtractiveCount, 0)); + tiles[tileOffset] = vec4(ivec4( + 0, + tileNormalCount, + tileNormalCount + tileModulatedCount, + tileNormalCount + tileModulatedCount + tileSubtractiveCount)); + + vec3 pos = vec3(-316.0, 64.0, 621.0); + float radius = 200.0; + vec3 color = vec3(1.0, 1.0, 1.0); + float shadowIndex = -1025.0; + vec3 spotDir = vec3(0.0); + float lightType = 0.0; + float spotInnerAngle = 0.0; + float spotOuterAngle = 0.0; + float softShadowRadius = 0.0; + + tiles[tileOffset + 1] = vec4(pos, radius); + tiles[tileOffset + 2] = vec4(color, shadowIndex); + tiles[tileOffset + 3] = vec4(spotDir, lightType); + tiles[tileOffset + 4] = vec4(spotInnerAngle, spotOuterAngle, softShadowRadius, 0.0); } diff --git a/wadsrc/static/shaders/scene/frag_main.glsl b/wadsrc/static/shaders/scene/frag_main.glsl index 8b30d6dbb..def4164b3 100644 --- a/wadsrc/static/shaders/scene/frag_main.glsl +++ b/wadsrc/static/shaders/scene/frag_main.glsl @@ -21,6 +21,11 @@ void main() if (ClipDistanceA.x < 0 || ClipDistanceA.y < 0 || ClipDistanceA.z < 0 || ClipDistanceA.w < 0 || ClipDistanceB.x < 0) discard; #endif +#if defined(USE_LEVELMESH) + const int lightTileSize = 1 + 16 * 4; + uLightIndex = int(uint(gl_FragCoord.x) / 64 + uint(gl_FragCoord.y) / 64 * uLightTilesWidth) * lightTileSize; +#endif + Material material = CreateMaterial(); #ifndef NO_ALPHATEST diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index 56cafd54a..a994c66c8 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -73,7 +73,8 @@ layout(push_constant) uniform PushConstants #define uVertexColor lightdata[uDataIndex].uVertexColor #define uDesaturationFactor lightdata[uDataIndex].uDesaturationFactor #define uLightLevel lightdata[uDataIndex].uLightLevel -#define uLightIndex lightdata[uDataIndex].uLightIndex +//#define uLightIndex lightdata[uDataIndex].uLightIndex +int uLightIndex; #else #define uVertexColor data[uDataIndex].uVertexColor #define uDesaturationFactor data[uDataIndex].uDesaturationFactor