- add dynamic lights to softpoly and software renderer models
This commit is contained in:
parent
61f379c88f
commit
5464d2a577
13 changed files with 283 additions and 65 deletions
|
|
@ -77,9 +77,9 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x,
|
|||
queue->Push<PolySetViewportCommand>(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra);
|
||||
}
|
||||
|
||||
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip)
|
||||
void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld)
|
||||
{
|
||||
queue->Push<PolySetTransformCommand>(objectToClip);
|
||||
queue->Push<PolySetTransformCommand>(objectToClip, objectToWorld);
|
||||
}
|
||||
|
||||
void PolyTriangleDrawer::SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw)
|
||||
|
|
@ -114,9 +114,10 @@ void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, ui
|
|||
weaponScene = false;
|
||||
}
|
||||
|
||||
void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip)
|
||||
void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Mat4f *newObjectToWorld)
|
||||
{
|
||||
objectToClip = newObjectToClip;
|
||||
objectToWorld = newObjectToWorld;
|
||||
}
|
||||
|
||||
void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs)
|
||||
|
|
@ -235,18 +236,30 @@ void PolyTriangleThreadData::DrawArrays(const PolyDrawArgs &drawargs)
|
|||
ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const TriVertex &v)
|
||||
{
|
||||
// Apply transform to get clip coordinates:
|
||||
Vec4f position = (*objectToClip) * Vec4f(v.x, v.y, v.z, v.w);
|
||||
Vec4f objpos = Vec4f(v.x, v.y, v.z, v.w);
|
||||
Vec4f clippos = (*objectToClip) * objpos;
|
||||
|
||||
ShadedTriVertex sv;
|
||||
sv.x = position.X;
|
||||
sv.y = position.Y;
|
||||
sv.z = position.Z;
|
||||
sv.w = position.W;
|
||||
sv.x = clippos.X;
|
||||
sv.y = clippos.Y;
|
||||
sv.z = clippos.Z;
|
||||
sv.w = clippos.W;
|
||||
sv.u = v.u;
|
||||
sv.v = v.v;
|
||||
sv.worldX = v.x;
|
||||
sv.worldY = v.y;
|
||||
sv.worldZ = v.z;
|
||||
|
||||
if (!objectToWorld) // Identity matrix
|
||||
{
|
||||
sv.worldX = v.x;
|
||||
sv.worldY = v.y;
|
||||
sv.worldZ = v.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec4f worldpos = (*objectToWorld) * objpos;
|
||||
sv.worldX = worldpos.X;
|
||||
sv.worldY = worldpos.Y;
|
||||
sv.worldZ = worldpos.Z;
|
||||
}
|
||||
|
||||
// Calculate gl_ClipDistance[i]
|
||||
for (int i = 0; i < 3; i++)
|
||||
|
|
@ -576,13 +589,13 @@ PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread)
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip) : objectToClip(objectToClip)
|
||||
PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld)
|
||||
{
|
||||
}
|
||||
|
||||
void PolySetTransformCommand::Execute(DrawerThread *thread)
|
||||
{
|
||||
PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip);
|
||||
PolyTriangleThreadData::Get(thread)->SetTransform(objectToClip, objectToWorld);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw);
|
||||
static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided);
|
||||
static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable);
|
||||
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip);
|
||||
static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld);
|
||||
|
||||
static bool IsBgra();
|
||||
};
|
||||
|
|
@ -48,7 +48,7 @@ public:
|
|||
PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { }
|
||||
|
||||
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);
|
||||
void SetTransform(const Mat4f *objectToClip);
|
||||
void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld);
|
||||
void SetCullCCW(bool value) { ccw = value; }
|
||||
void SetTwoSided(bool value) { twosided = value; }
|
||||
void SetWeaponScene(bool value) { weaponScene = value; }
|
||||
|
|
@ -88,6 +88,7 @@ private:
|
|||
bool twosided = false;
|
||||
bool weaponScene = false;
|
||||
const Mat4f *objectToClip = nullptr;
|
||||
const Mat4f *objectToWorld = nullptr;
|
||||
|
||||
enum { max_additional_vertices = 16 };
|
||||
};
|
||||
|
|
@ -95,13 +96,14 @@ private:
|
|||
class PolySetTransformCommand : public DrawerCommand
|
||||
{
|
||||
public:
|
||||
PolySetTransformCommand(const Mat4f *objectToClip);
|
||||
PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld);
|
||||
|
||||
void Execute(DrawerThread *thread) override;
|
||||
FString DebugInfo() override { return "PolySetTransform"; }
|
||||
|
||||
private:
|
||||
const Mat4f *objectToClip;
|
||||
const Mat4f *objectToWorld;
|
||||
};
|
||||
|
||||
class PolySetCullCCWCommand : public DrawerCommand
|
||||
|
|
|
|||
|
|
@ -480,6 +480,29 @@ void DrawSpanOpt32(int y, int x0, int x1, const TriDrawTriangleArgs *args)
|
|||
worldnormalZ = args->uniforms->Normal().Z;
|
||||
dynlightcolor = args->uniforms->DynLightColor();
|
||||
|
||||
// The normal vector cannot be uniform when drawing models. Calculate and use the face normal:
|
||||
if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f)
|
||||
{
|
||||
float dx1 = args->v2->worldX - args->v1->worldX;
|
||||
float dy1 = args->v2->worldY - args->v1->worldY;
|
||||
float dz1 = args->v2->worldZ - args->v1->worldZ;
|
||||
float dx2 = args->v3->worldX - args->v1->worldX;
|
||||
float dy2 = args->v3->worldY - args->v1->worldY;
|
||||
float dz2 = args->v3->worldZ - args->v1->worldZ;
|
||||
worldnormalX = dy1 * dz2 - dz1 * dy2;
|
||||
worldnormalY = dz1 * dx2 - dx1 * dz2;
|
||||
worldnormalZ = dx1 * dy2 - dy1 * dx2;
|
||||
float lensqr = worldnormalX * worldnormalX + worldnormalY * worldnormalY + worldnormalZ * worldnormalZ;
|
||||
#ifndef NO_SSE
|
||||
float rcplen = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(lensqr)));
|
||||
#else
|
||||
float rcplen = 1.0f / sqrt(lensqr);
|
||||
#endif
|
||||
worldnormalX *= rcplen;
|
||||
worldnormalY *= rcplen;
|
||||
worldnormalZ *= rcplen;
|
||||
}
|
||||
|
||||
int affineOffset = x0 / 16 * 16 - x0;
|
||||
float posLightW = posW + stepW * affineOffset;
|
||||
posWorldX = posWorldX + stepWorldX * affineOffset;
|
||||
|
|
@ -1067,6 +1090,29 @@ void DrawSpanOpt8(int y, int x0, int x1, const TriDrawTriangleArgs *args)
|
|||
worldnormalZ = args->uniforms->Normal().Z;
|
||||
dynlightcolor = args->uniforms->DynLightColor();
|
||||
|
||||
// The normal vector cannot be uniform when drawing models. Calculate and use the face normal:
|
||||
if (worldnormalX == 0.0f && worldnormalY == 0.0f && worldnormalZ == 0.0f)
|
||||
{
|
||||
float dx1 = args->v2->worldX - args->v1->worldX;
|
||||
float dy1 = args->v2->worldY - args->v1->worldY;
|
||||
float dz1 = args->v2->worldZ - args->v1->worldZ;
|
||||
float dx2 = args->v3->worldX - args->v1->worldX;
|
||||
float dy2 = args->v3->worldY - args->v1->worldY;
|
||||
float dz2 = args->v3->worldZ - args->v1->worldZ;
|
||||
worldnormalX = dy1 * dz2 - dz1 * dy2;
|
||||
worldnormalY = dz1 * dx2 - dx1 * dz2;
|
||||
worldnormalZ = dx1 * dy2 - dy1 * dx2;
|
||||
float lensqr = worldnormalX * worldnormalX + worldnormalY * worldnormalY + worldnormalZ * worldnormalZ;
|
||||
#ifndef NO_SSE
|
||||
float rcplen = _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(lensqr)));
|
||||
#else
|
||||
float rcplen = 1.0f / sqrt(lensqr);
|
||||
#endif
|
||||
worldnormalX *= rcplen;
|
||||
worldnormalY *= rcplen;
|
||||
worldnormalZ *= rcplen;
|
||||
}
|
||||
|
||||
int affineOffset = x0 / 16 * 16 - x0;
|
||||
float posLightW = posW + stepW * affineOffset;
|
||||
posWorldX = posWorldX + stepWorldX * affineOffset;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue