- hook up dynamic lights

This commit is contained in:
Magnus Norddahl 2019-07-25 04:19:05 +02:00
parent a55412fcf6
commit 97a4f25771
7 changed files with 101 additions and 12 deletions

View file

@ -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;

View file

@ -89,19 +89,13 @@ void PolyVertexInputAssembly::Load(PolyTriangleThreadData *thread, const void *v
const float *attrVertex = reinterpret_cast<const float*>(vertex + mOffsets[VATTR_VERTEX]);
const float *attrTexcoord = reinterpret_cast<const float*>(vertex + mOffsets[VATTR_TEXCOORD]);
const uint8_t *attrColor = reinterpret_cast<const uint8_t*>(vertex + mOffsets[VATTR_COLOR]);
const uint32_t* attrNormal = reinterpret_cast<const uint32_t*>(vertex + mOffsets[VATTR_NORMAL]);
const uint32_t* attrNormal2 = reinterpret_cast<const uint32_t*>(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<uint32_t>(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);
}
}
/////////////////////////////////////////////////////////////////////////////

View file

@ -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()

View file

@ -76,6 +76,8 @@ private:
void CheckCanvas();
IDataBuffer *mLightBuffer = nullptr;
std::unique_ptr<PolyRenderState> mRenderState;
std::unique_ptr<DCanvas> mCanvas;
std::unique_ptr<PolyDepthStencil> mDepthStencil;

View file

@ -108,6 +108,11 @@ void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, cons
queue->Push<PolySetIndexBufferCommand>(elements);
}
void PolyTriangleDrawer::SetLightBuffer(const DrawerCommandQueuePtr& queue, const void *lights)
{
queue->Push<PolySetLightBufferCommand>(lights);
}
void PolyTriangleDrawer::PushDrawArgs(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args)
{
queue->Push<PolyPushDrawArgsCommand>(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<int>(lightRange.X) + start;
int modulatedEnd = static_cast<int>(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];

View file

@ -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:

View file

@ -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++)
{