From 97a4f2577133306e0f6126e0777d8904b711bc4c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Thu, 25 Jul 2019 04:19:05 +0200 Subject: [PATCH] - hook up dynamic lights --- .../hwrenderer/dynlights/hw_lightbuffer.cpp | 2 +- .../polyrenderer/backend/poly_buffers.cpp | 40 ++++++++++++++---- .../polyrenderer/backend/poly_framebuffer.cpp | 7 +++- .../polyrenderer/backend/poly_framebuffer.h | 2 + .../polyrenderer/drawers/poly_triangle.cpp | 42 +++++++++++++++++++ .../polyrenderer/drawers/poly_triangle.h | 16 +++++++ .../polyrenderer/drawers/poly_vertex_shader.h | 4 +- 7 files changed, 101 insertions(+), 12 deletions(-) diff --git a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp index 68a1fad2d..30326155f 100644 --- a/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp +++ b/src/rendering/hwrenderer/dynlights/hw_lightbuffer.cpp @@ -44,7 +44,7 @@ FLightBuffer::FLightBuffer() // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. // We only want to disable using SSBOs for lights but not disable the feature entirely. // Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD. - if (screen->IsVulkan() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel"))) + if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel"))) { mBufferType = true; mBlockAlign = 0; diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index 392684532..5aa713d84 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -89,19 +89,13 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); const uint8_t *attrColor = reinterpret_cast(vertex + mOffsets[VATTR_COLOR]); + const uint32_t* attrNormal = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL]); + const uint32_t* attrNormal2 = reinterpret_cast(vertex + mOffsets[VATTR_NORMAL2]); thread->mainVertexShader.aPosition = { attrVertex[0], attrVertex[1], attrVertex[2], 1.0f }; thread->mainVertexShader.aTexCoord = { attrTexcoord[0], attrTexcoord[1] }; - if (UseVertexData) - { - uint32_t r = attrColor[0]; - uint32_t g = attrColor[1]; - uint32_t b = attrColor[2]; - uint32_t a = attrColor[3]; - thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b); - } - else + if ((UseVertexData & 1) == 0) { const auto &c = thread->mainVertexShader.Data.uVertexColor; thread->mainVertexShader.aColor = MAKEARGB( @@ -111,6 +105,34 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v static_cast(c.Z * 255.0f + 0.5f) ); } + else + { + uint32_t r = attrColor[0]; + uint32_t g = attrColor[1]; + uint32_t b = attrColor[2]; + uint32_t a = attrColor[3]; + thread->mainVertexShader.aColor = MAKEARGB(a, r, g, b); + } + + if ((UseVertexData & 2) == 0) + { + const auto &n = thread->mainVertexShader.Data.uVertexNormal; + thread->mainVertexShader.aNormal = Vec4f(n.X, n.Y, n.Z, 1.0); + thread->mainVertexShader.aNormal2 = thread->mainVertexShader.aNormal; + } + else + { + int n = *attrNormal; + int n2 = *attrNormal2; + float x = ((n << 22) >> 22) / 512.0f; + float y = ((n << 12) >> 22) / 512.0f; + float z = ((n << 2) >> 22) / 512.0f; + float x2 = ((n2 << 22) >> 22) / 512.0f; + float y2 = ((n2 << 12) >> 22) / 512.0f; + float z2 = ((n2 << 2) >> 22) / 512.0f; + thread->mainVertexShader.aNormal = Vec4f(x, y, z, 0.0f); + thread->mainVertexShader.aNormal2 = Vec4f(x2, y2, z2, 0.0f); + } } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index c5b689abe..023298806 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -100,6 +100,8 @@ void PolyFrameBuffer::InitializeState() mViewpoints = new HWViewpointBuffer; mLights = new FLightBuffer(); + PolyTriangleDrawer::SetLightBuffer(GetDrawCommands(), mLightBuffer->Memory()); + CheckCanvas(); } @@ -485,7 +487,10 @@ IIndexBuffer *PolyFrameBuffer::CreateIndexBuffer() IDataBuffer *PolyFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { - return new PolyDataBuffer(bindingpoint, ssbo, needsresize); + IDataBuffer *buffer = new PolyDataBuffer(bindingpoint, ssbo, needsresize); + if (bindingpoint == LIGHTBUF_BINDINGPOINT) + mLightBuffer = buffer; + return buffer; } void PolyFrameBuffer::SetTextureFilterMode() diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 8e2eae427..08494a117 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -76,6 +76,8 @@ private: void CheckCanvas(); + IDataBuffer *mLightBuffer = nullptr; + std::unique_ptr mRenderState; std::unique_ptr mCanvas; std::unique_ptr mDepthStencil; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index f87c01960..11c20564e 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -108,6 +108,11 @@ void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, cons queue->Push(elements); } +void PolyTriangleDrawer::SetLightBuffer(const DrawerCommandQueuePtr& queue, const void *lights) +{ + queue->Push(lights); +} + void PolyTriangleDrawer::PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) { queue->Push(args); @@ -309,6 +314,42 @@ void PolyTriangleThreadData::PushStreamData(const StreamData &data, const PolyPu drawargs.SetLight(GetColorTable(cm), 255, mainVertexShader.Viewpoint->mGlobVis * 32.0f, true); } + int numLights = 0; + if (constants.uLightIndex >= 0) + { + const FVector4 &lightRange = lights[constants.uLightIndex]; + static_assert(sizeof(FVector4) == 16, "sizeof(FVector4) is not 16 bytes"); + if (lightRange.Y > lightRange.X) + { + int start = constants.uLightIndex + 1; + int modulatedStart = static_cast(lightRange.X) + start; + int modulatedEnd = static_cast(lightRange.Y) + start; + for (int i = modulatedStart; i < modulatedEnd; i += 4) + { + if (numLights == maxPolyLights) + break; + + auto &lightpos = lights[i]; + auto &lightcolor = lights[i + 1]; + //auto &lightspot1 = lights[i + 2]; + //auto &lightspot2 = lights[i + 3]; + uint32_t r = (int)clamp(lightcolor.X * 255.0f, 0.0f, 255.0f); + uint32_t g = (int)clamp(lightcolor.Y * 255.0f, 0.0f, 255.0f); + uint32_t b = (int)clamp(lightcolor.Z * 255.0f, 0.0f, 255.0f); + + auto& polylight = polyLights[numLights++]; + polylight.x = lightpos.X; + polylight.y = lightpos.Y; + polylight.z = lightpos.Z; + polylight.radius = 256.0f / lightpos.W; + polylight.color = (r << 16) | (g << 8) | b; + if (lightcolor.W < 0.0f) + polylight.radius = -polylight.radius; + } + } + } + drawargs.SetLights(polyLights, numLights); + if (SpecialEffect != EFF_NONE) { // To do: need new drawers for these @@ -794,6 +835,7 @@ void PolyTriangleThreadData::DrawShadedTriangle(const ShadedTriVertex *const* ve return; drawargs.SetColor(vert[0]->vColor, 0); + drawargs.SetNormal(FVector3(vert[0]->vWorldNormal.X, vert[0]->vWorldNormal.Y, vert[0]->vWorldNormal.Z)); // Cull, clip and generate additional vertices as needed ScreenTriVertex clippedvert[max_additional_vertices]; diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 683ebbd40..d1e2f6fcb 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -42,6 +42,7 @@ public: static void SetInputAssembly(const DrawerCommandQueuePtr &queue, PolyInputAssembly *input); static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void SetLightBuffer(const DrawerCommandQueuePtr& queue, const void *lights); static void SetViewpointUniforms(const DrawerCommandQueuePtr &queue, const HWViewpointUniforms *uniforms); static void SetDepthClamp(const DrawerCommandQueuePtr &queue, bool on); static void SetDepthMask(const DrawerCommandQueuePtr &queue, bool on); @@ -143,6 +144,7 @@ public: void SetInputAssembly(PolyInputAssembly *input) { inputAssembly = input; } void SetVertexBuffer(const void *data) { vertices = data; } void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } + void SetLightBuffer(const void *data) { lights = (const FVector4 *)data; } void SetViewpointUniforms(const HWViewpointUniforms *uniforms); void SetDepthClamp(bool on); void SetDepthMask(bool on); @@ -237,6 +239,10 @@ public: const void *vertices = nullptr; const unsigned int *elements = nullptr; + const FVector4 *lights = nullptr; + + enum { maxPolyLights = 16 }; + PolyLight polyLights[maxPolyLights]; PolyMainVertexShader mainVertexShader; @@ -455,6 +461,16 @@ private: const void *indices; }; +class PolySetLightBufferCommand : public PolyDrawerCommand +{ +public: + PolySetLightBufferCommand(const void *lights) : lights(lights) { } + void Execute(DrawerThread *thread) override { PolyTriangleThreadData::Get(thread)->SetLightBuffer(lights); } + +private: + const void *lights; +}; + class PolySetInputAssemblyCommand : public PolyDrawerCommand { public: diff --git a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h index a431f8941..6c080552f 100644 --- a/src/rendering/polyrenderer/drawers/poly_vertex_shader.h +++ b/src/rendering/polyrenderer/drawers/poly_vertex_shader.h @@ -17,6 +17,7 @@ public: Vec4f vTexCoord; uint32_t vColor; Vec4f pixelpos; + Vec4f vWorldNormal; }; class PolyMainVertexShader : public ShadedTriVertex @@ -33,7 +34,6 @@ public: // Output Vec3f glowdist; Vec3f gradientdist; - Vec4f vWorldNormal; Vec4f vEyeNormal; // Defines @@ -245,6 +245,8 @@ public: vColor = drawargs->Color(); + vWorldNormal = { drawargs->Normal().X, drawargs->Normal().Y, drawargs->Normal().Z }; + // Calculate gl_ClipDistance[i] for (int i = 0; i < 3; i++) {