Skip to content

Commit acc7997

Browse files
author
Rachael Alexanderson
committed
Merge branch 'master' of https://github.com/coelckers/gzdoom
2 parents de8b119 + 2abf700 commit acc7997

14 files changed

+307
-73
lines changed

Diff for: src/hwrenderer/scene/hw_spritelight.cpp

+1-43
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "hwrenderer/dynlights/hw_dynlightdata.h"
3535
#include "hwrenderer/dynlights/hw_shadowmap.h"
3636
#include "hwrenderer/scene/hw_drawinfo.h"
37+
#include "r_data/models/models.h"
3738

3839
template<class T>
3940
T smoothstep(const T edge0, const T edge1, const T x)
@@ -138,49 +139,6 @@ void HWDrawInfo::GetDynSpriteLight(AActor *thing, particle_t *particle, float *o
138139
}
139140
}
140141

141-
// Check if circle potentially intersects with node AABB
142-
static bool CheckBBoxCircle(float *bbox, float x, float y, float radiusSquared)
143-
{
144-
float centerX = (bbox[BOXRIGHT] + bbox[BOXLEFT]) * 0.5f;
145-
float centerY = (bbox[BOXBOTTOM] + bbox[BOXTOP]) * 0.5f;
146-
float extentX = (bbox[BOXRIGHT] - bbox[BOXLEFT]) * 0.5f;
147-
float extentY = (bbox[BOXBOTTOM] - bbox[BOXTOP]) * 0.5f;
148-
float aabbRadiusSquared = extentX * extentX + extentY * extentY;
149-
x -= centerX;
150-
y -= centerY;
151-
float dist = x * x + y * y;
152-
return dist <= radiusSquared + aabbRadiusSquared;
153-
}
154-
155-
template<typename Callback>
156-
void BSPNodeWalkCircle(void *node, float x, float y, float radiusSquared, const Callback &callback)
157-
{
158-
while (!((size_t)node & 1))
159-
{
160-
node_t *bsp = (node_t *)node;
161-
162-
if (CheckBBoxCircle(bsp->bbox[0], x, y, radiusSquared))
163-
BSPNodeWalkCircle(bsp->children[0], x, y, radiusSquared, callback);
164-
165-
if (!CheckBBoxCircle(bsp->bbox[1], x, y, radiusSquared))
166-
return;
167-
168-
node = bsp->children[1];
169-
}
170-
171-
subsector_t *sub = (subsector_t *)((uint8_t *)node - 1);
172-
callback(sub);
173-
}
174-
175-
template<typename Callback>
176-
void BSPWalkCircle(float x, float y, float radiusSquared, const Callback &callback)
177-
{
178-
if (level.nodes.Size() == 0)
179-
callback(&level.subsectors[0]);
180-
else
181-
BSPNodeWalkCircle(level.HeadNode(), x, y, radiusSquared, callback);
182-
}
183-
184142
// static so that we build up a reserve (memory allocations stop)
185143
// For multithread processing each worker thread needs its own copy, though.
186144
static thread_local TArray<ADynamicLight*> addedLightsArray;

Diff for: src/polyrenderer/drawers/poly_triangle.cpp

+26-13
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x,
7777
queue->Push<PolySetViewportCommand>(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra);
7878
}
7979

80-
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip)
80+
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld)
8181
{
82-
queue->Push<PolySetTransformCommand>(objectToClip);
82+
queue->Push<PolySetTransformCommand>(objectToClip, objectToWorld);
8383
}
8484

8585
void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw)
@@ -114,9 +114,10 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui
114114
weaponScene = false;
115115
}
116116

117-
void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip)
117+
void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Mat4f *newObjectToWorld)
118118
{
119119
objectToClip = newObjectToClip;
120+
objectToWorld = newObjectToWorld;
120121
}
121122

122123
void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs)
@@ -235,18 +236,30 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs)
235236
ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v)
236237
{
237238
// Apply transform to get clip coordinates:
238-
Vec4f position = (*objectToClip) * Vec4f(v.x, v.y, v.z, v.w);
239+
Vec4f objpos = Vec4f(v.x, v.y, v.z, v.w);
240+
Vec4f clippos = (*objectToClip) * objpos;
239241

240242
ShadedTriVertex sv;
241-
sv.x = position.X;
242-
sv.y = position.Y;
243-
sv.z = position.Z;
244-
sv.w = position.W;
243+
sv.x = clippos.X;
244+
sv.y = clippos.Y;
245+
sv.z = clippos.Z;
246+
sv.w = clippos.W;
245247
sv.u = v.u;
246248
sv.v = v.v;
247-
sv.worldX = v.x;
248-
sv.worldY = v.y;
249-
sv.worldZ = v.z;
249+
250+
if (!objectToWorld) // Identity matrix
251+
{
252+
sv.worldX = v.x;
253+
sv.worldY = v.y;
254+
sv.worldZ = v.z;
255+
}
256+
else
257+
{
258+
Vec4f worldpos = (*objectToWorld) * objpos;
259+
sv.worldX = worldpos.X;
260+
sv.worldY = worldpos.Y;
261+
sv.worldZ = worldpos.Z;
262+
}
250263

251264
// Calculate gl_ClipDistance[i]
252265
for (int i = 0; i < 3; i++)
@@ -576,13 +589,13 @@ PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread)
576589

577590
/////////////////////////////////////////////////////////////////////////////
578591

579-
PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip) : objectToClip(objectToClip)
592+
PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld)
580593
{
581594
}
582595

583596
void PolySetTransformCommand::Execute(DrawerThread *thread)
584597
{
585-
PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip);
598+
PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip, objectToWorld);
586599
}
587600

588601
/////////////////////////////////////////////////////////////////////////////

Diff for: src/polyrenderer/drawers/poly_triangle.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class PolyTriangleDrawer
3737
static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw);
3838
static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided);
3939
static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable);
40-
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip);
40+
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld);
4141

4242
static bool IsBgra();
4343
};
@@ -48,7 +48,7 @@ class PolyTriangleThreadData
4848
PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { }
4949

5050
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra);
51-
void SetTransform(const Mat4f *objectToClip);
51+
void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld);
5252
void SetCullCCW(bool value) { ccw = value; }
5353
void SetTwoSided(bool value) { twosided = value; }
5454
void SetWeaponScene(bool value) { weaponScene = value; }
@@ -88,20 +88,22 @@ class PolyTriangleThreadData
8888
bool twosided = false;
8989
bool weaponScene = false;
9090
const Mat4f *objectToClip = nullptr;
91+
const Mat4f *objectToWorld = nullptr;
9192

9293
enum { max_additional_vertices = 16 };
9394
};
9495

9596
class PolySetTransformCommand : public DrawerCommand
9697
{
9798
public:
98-
PolySetTransformCommand(const Mat4f *objectToClip);
99+
PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld);
99100

100101
void Execute(DrawerThread *thread) override;
101102
FString DebugInfo() override { return "PolySetTransform"; }
102103

103104
private:
104105
const Mat4f *objectToClip;
106+
const Mat4f *objectToWorld;
105107
};
106108

107109
class PolySetCullCCWCommand : public DrawerCommand

Diff for: src/polyrenderer/drawers/screen_triangle.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,29 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
480480
worldnormalZ = args->uniforms->Normal().Z;
481481
dynlightcolor = args->uniforms->DynLightColor();
482482

483+
// The normal vector cannot be uniform when drawing models. Calculate and use the face normal:
484+
if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f)
485+
{
486+
float dx1 = args->v2->worldX - args->v1->worldX;
487+
float dy1 = args->v2->worldY - args->v1->worldY;
488+
float dz1 = args->v2->worldZ - args->v1->worldZ;
489+
float dx2 = args->v3->worldX - args->v1->worldX;
490+
float dy2 = args->v3->worldY - args->v1->worldY;
491+
float dz2 = args->v3->worldZ - args->v1->worldZ;
492+
worldnormalX = dy1 * dz2 - dz1 * dy2;
493+
worldnormalY = dz1 * dx2 - dx1 * dz2;
494+
worldnormalZ = dx1 * dy2 - dy1 * dx2;
495+
float lensqr = worldnormalX * worldnormalX + worldnormalY * worldnormalY + worldnormalZ * worldnormalZ;
496+
#ifndef NO_SSE
497+
float rcplen = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(lensqr)));
498+
#else
499+
float rcplen = 1.0f / sqrt(lensqr);
500+
#endif
501+
worldnormalX *= rcplen;
502+
worldnormalY *= rcplen;
503+
worldnormalZ *= rcplen;
504+
}
505+
483506
int affineOffset = x0 / 16 * 16 - x0;
484507
float posLightW = posW + stepW * affineOffset;
485508
posWorldX = posWorldX + stepWorldX * affineOffset;
@@ -1067,6 +1090,29 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
10671090
worldnormalZ = args->uniforms->Normal().Z;
10681091
dynlightcolor = args->uniforms->DynLightColor();
10691092

1093+
// The normal vector cannot be uniform when drawing models. Calculate and use the face normal:
1094+
if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f)
1095+
{
1096+
float dx1 = args->v2->worldX - args->v1->worldX;
1097+
float dy1 = args->v2->worldY - args->v1->worldY;
1098+
float dz1 = args->v2->worldZ - args->v1->worldZ;
1099+
float dx2 = args->v3->worldX - args->v1->worldX;
1100+
float dy2 = args->v3->worldY - args->v1->worldY;
1101+
float dz2 = args->v3->worldZ - args->v1->worldZ;
1102+
worldnormalX = dy1 * dz2 - dz1 * dy2;
1103+
worldnormalY = dz1 * dx2 - dx1 * dz2;
1104+
worldnormalZ = dx1 * dy2 - dy1 * dx2;
1105+
float lensqr = worldnormalX * worldnormalX + worldnormalY * worldnormalY + worldnormalZ * worldnormalZ;
1106+
#ifndef NO_SSE
1107+
float rcplen = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(lensqr)));
1108+
#else
1109+
float rcplen = 1.0f / sqrt(lensqr);
1110+
#endif
1111+
worldnormalX *= rcplen;
1112+
worldnormalY *= rcplen;
1113+
worldnormalZ *= rcplen;
1114+
}
1115+
10701116
int affineOffset = x0 / 16 * 16 - x0;
10711117
float posLightW = posW + stepW * affineOffset;
10721118
posWorldX = posWorldX + stepWorldX * affineOffset;

Diff for: src/polyrenderer/poly_renderthread.h

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class RenderMemory;
3232
class PolyTranslucentObject;
3333
class PolyDrawSectorPortal;
3434
class PolyDrawLinePortal;
35+
class ADynamicLight;
3536

3637
class PolyRenderThread
3738
{
@@ -53,6 +54,8 @@ class PolyRenderThread
5354
std::vector<std::unique_ptr<PolyDrawSectorPortal>> SectorPortals;
5455
std::vector<std::unique_ptr<PolyDrawLinePortal>> LinePortals;
5556

57+
TArray<ADynamicLight*> AddedLightsArray;
58+
5659
// Make sure texture can accessed safely
5760
void PrepareTexture(FTexture *texture, FRenderStyle style);
5861

Diff for: src/polyrenderer/scene/poly_model.cpp

+69-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
void PolyRenderModel(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue, float x, float y, float z, FSpriteModelFrame *smf, AActor *actor)
3737
{
3838
PolyModelRenderer renderer(thread, worldToClip, stencilValue);
39+
renderer.AddLights(actor);
3940
renderer.RenderModel(x, y, z, smf, actor);
4041
}
4142

@@ -51,6 +52,70 @@ PolyModelRenderer::PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worl
5152
{
5253
}
5354

55+
void PolyModelRenderer::AddLights(AActor *actor)
56+
{
57+
if (gl_lights && actor)
58+
{
59+
auto &addedLights = Thread->AddedLightsArray;
60+
61+
addedLights.Clear();
62+
63+
float x = (float)actor->X();
64+
float y = (float)actor->Y();
65+
float z = (float)actor->Center();
66+
float radiusSquared = (float)(actor->renderradius * actor->renderradius);
67+
68+
BSPWalkCircle(x, y, radiusSquared, [&](subsector_t *subsector) // Iterate through all subsectors potentially touched by actor
69+
{
70+
FLightNode * node = subsector->lighthead;
71+
while (node) // check all lights touching a subsector
72+
{
73+
ADynamicLight *light = node->lightsource;
74+
if (light->visibletoplayer && !(light->flags2&MF2_DORMANT) && (!(light->lightflags&LF_DONTLIGHTSELF) || light->target != actor) && !(light->lightflags&LF_DONTLIGHTACTORS))
75+
{
76+
int group = subsector->sector->PortalGroup;
77+
DVector3 pos = light->PosRelative(group);
78+
float radius = (float)(light->GetRadius() + actor->renderradius);
79+
double dx = pos.X - x;
80+
double dy = pos.Y - y;
81+
double dz = pos.Z - z;
82+
double distSquared = dx * dx + dy * dy + dz * dz;
83+
if (distSquared < radius * radius) // Light and actor touches
84+
{
85+
if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
86+
{
87+
addedLights.Push(light);
88+
}
89+
}
90+
}
91+
node = node->nextLight;
92+
}
93+
});
94+
95+
NumLights = addedLights.Size();
96+
Lights = Thread->FrameMemory->AllocMemory<PolyLight>(NumLights);
97+
for (int i = 0; i < NumLights; i++)
98+
{
99+
ADynamicLight *lightsource = addedLights[i];
100+
101+
bool is_point_light = (lightsource->lightflags & LF_ATTENUATE) != 0;
102+
103+
uint32_t red = lightsource->GetRed();
104+
uint32_t green = lightsource->GetGreen();
105+
uint32_t blue = lightsource->GetBlue();
106+
107+
PolyLight &light = Lights[i];
108+
light.x = (float)lightsource->X();
109+
light.y = (float)lightsource->Y();
110+
light.z = (float)lightsource->Z();
111+
light.radius = 256.0f / lightsource->GetRadius();
112+
light.color = (red << 16) | (green << 8) | blue;
113+
if (is_point_light)
114+
light.radius = -light.radius;
115+
}
116+
}
117+
}
118+
54119
void PolyModelRenderer::BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored)
55120
{
56121
ModelActor = actor;
@@ -139,8 +204,9 @@ void PolyModelRenderer::SetTransform()
139204
swapYZ.Matrix[1 + 2 * 4] = 1.0f;
140205
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
141206
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
207+
ObjectToWorld = swapYZ * ObjectToWorld;
142208

143-
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>(WorldToClip * swapYZ * ObjectToWorld));
209+
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>(WorldToClip * ObjectToWorld), Thread->FrameMemory->NewObject<Mat4f>(ObjectToWorld));
144210
}
145211

146212
void PolyModelRenderer::DrawArrays(int start, int count)
@@ -156,6 +222,7 @@ void PolyModelRenderer::DrawArrays(int start, int count)
156222

157223
PolyDrawArgs args;
158224
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
225+
args.SetLights(Lights, NumLights);
159226
args.SetStencilTestValue(StencilValue);
160227
args.SetClipPlane(0, PolyClipPlane());
161228
args.SetStyle(ModelActor->RenderStyle, ModelActor->Alpha, ModelActor->fillcolor, ModelActor->Translation, SkinTexture, fullbrightSprite);
@@ -178,6 +245,7 @@ void PolyModelRenderer::DrawElements(int numIndices, size_t offset)
178245

179246
PolyDrawArgs args;
180247
args.SetLight(GetColorTable(sector->Colormap, sector->SpecialColors[sector_t::sprites], true), lightlevel, PolyRenderer::Instance()->Light.SpriteGlobVis(foggy), fullbrightSprite);
248+
args.SetLights(Lights, NumLights);
181249
args.SetStencilTestValue(StencilValue);
182250
args.SetClipPlane(0, PolyClipPlane());
183251
args.SetStyle(ModelActor->RenderStyle, ModelActor->Alpha, ModelActor->fillcolor, ModelActor->Translation, SkinTexture, fullbrightSprite);

Diff for: src/polyrenderer/scene/poly_model.h

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class PolyModelRenderer : public FModelRenderer
3434
public:
3535
PolyModelRenderer(PolyRenderThread *thread, const Mat4f &worldToClip, uint32_t stencilValue);
3636

37+
void AddLights(AActor *actor);
38+
3739
ModelRendererType GetType() const override { return PolyModelRendererType; }
3840

3941
void BeginDrawModel(AActor *actor, FSpriteModelFrame *smf, const VSMatrix &objectToWorldMatrix, bool mirrored) override;
@@ -61,6 +63,8 @@ class PolyModelRenderer : public FModelRenderer
6163
unsigned int *IndexBuffer = nullptr;
6264
TriVertex *VertexBuffer = nullptr;
6365
float InterpolationFactor = 0.0;
66+
PolyLight *Lights = nullptr;
67+
int NumLights = 0;
6468
};
6569

6670
class PolyModelVertexBuffer : public IModelVertexBuffer

0 commit comments

Comments
 (0)