Merge tracelights
This commit is contained in:
commit
fd2ae4865c
18 changed files with 1156 additions and 210 deletions
|
|
@ -56,6 +56,8 @@ DoomLevelMesh::DoomLevelMesh(FLevelLocals &doomMap)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collision = std::make_unique<TriangleMeshShape>(MeshVertices.Data(), MeshVertices.Size(), MeshElements.Data(), MeshElements.Size());
|
||||
}
|
||||
|
||||
void DoomLevelMesh::CreateSideSurfaces(FLevelLocals &doomMap, side_t *side)
|
||||
|
|
|
|||
|
|
@ -59,21 +59,7 @@ void HWDecal::DrawDecal(HWDrawInfo *di, FRenderState &state)
|
|||
if (!di->isFullbrightScene()) DecalColor = DecalColor.Modulate(frontsector->SpecialColors[sector_t::sprites]);
|
||||
|
||||
state.SetObjectColor(DecalColor);
|
||||
|
||||
state.SetLightIndex(dynlightindex);
|
||||
|
||||
// add light probe contribution
|
||||
if (di->Level->LightProbes.Size() > 0)
|
||||
{
|
||||
double x, y;
|
||||
decal->GetXY(decal->Side, x, y);
|
||||
LightProbe *probe = FindLightProbe(di->Level, x, y, decal->GetRealZ(decal->Side) * 0.5);
|
||||
if (probe)
|
||||
{
|
||||
state.SetDynLight(probe->Red, probe->Green, probe->Blue);
|
||||
}
|
||||
}
|
||||
|
||||
state.SetTextureMode(decal->RenderStyle);
|
||||
state.SetRenderStyle(decal->RenderStyle);
|
||||
state.SetMaterial(texture, UF_Sprite, 0, CLAMP_XY, decal->Translation, -1);
|
||||
|
|
@ -197,6 +183,11 @@ void HWWall::DrawDecalsForMirror(HWDrawInfo *di, FRenderState &state, TArray<HWD
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static float mix(float a, float b, float t)
|
||||
{
|
||||
return a * (1.0f - t) + b * t;
|
||||
}
|
||||
|
||||
void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &normal)
|
||||
{
|
||||
line_t * line = seg->linedef;
|
||||
|
|
@ -342,7 +333,31 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
|||
dv[UL].u = dv[LL].u = lefttex / decalscale;
|
||||
dv[LR].u = dv[UR].u = righttex / decalscale;
|
||||
dv[LL].v = dv[LR].v = 1.f;
|
||||
|
||||
|
||||
// lightmap texture index
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
dv[i].lindex = lindex;
|
||||
}
|
||||
|
||||
// lightmap texture coordinates
|
||||
float tleft = left / linelength;
|
||||
float tright = right / linelength;
|
||||
float tuplft = ztop[0] != zbottom[0] ? (dv[UL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f;
|
||||
float tuprgt = ztop[1] != zbottom[1] ? (dv[UR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f;
|
||||
float tlolft = ztop[0] != zbottom[0] ? (dv[LL].z - zbottom[0]) / (ztop[0] - zbottom[0]) : 0.0f;
|
||||
float tlorgt = ztop[1] != zbottom[1] ? (dv[LR].z - zbottom[1]) / (ztop[1] - zbottom[1]) : 0.0f;
|
||||
|
||||
dv[LL].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tleft);
|
||||
dv[LR].lu = mix(lightuv[LOLFT].u, lightuv[LORGT].u, tright);
|
||||
dv[UL].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tleft);
|
||||
dv[UR].lu = mix(lightuv[UPLFT].u, lightuv[UPRGT].u, tright);
|
||||
|
||||
dv[LL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tlolft);
|
||||
dv[LR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tlorgt);
|
||||
dv[UL].lv = mix(lightuv[LOLFT].v, lightuv[UPLFT].v, tuplft);
|
||||
dv[UR].lv = mix(lightuv[LORGT].v, lightuv[UPRGT].v, tuprgt);
|
||||
|
||||
// now clip to the top plane
|
||||
float vzt = (ztop[UL] - ztop[LL]) / linelength;
|
||||
float topleft = ztop[LL] + vzt * left;
|
||||
|
|
@ -356,8 +371,12 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
|||
{
|
||||
// decal has to be clipped at the top
|
||||
// let texture clamping handle all extreme cases
|
||||
dv[UL].v = (dv[UL].z - topleft) / (dv[UL].z - dv[LL].z)*dv[LL].v;
|
||||
dv[UR].v = (dv[UR].z - topright) / (dv[UR].z - dv[LR].z)*dv[LR].v;
|
||||
float t0 = (dv[UL].z - topleft) / (dv[UL].z - dv[LL].z);
|
||||
float t1 = (dv[UR].z - topright) / (dv[UR].z - dv[LR].z);
|
||||
dv[UL].v = t0 * dv[LL].v;
|
||||
dv[UR].v = t1 * dv[LR].v;
|
||||
dv[UL].lv = mix(dv[UL].lv, dv[LL].lv, t0);
|
||||
dv[UR].lv = mix(dv[UR].lv, dv[LR].lv, t1);
|
||||
dv[UL].z = topleft;
|
||||
dv[UR].z = topright;
|
||||
}
|
||||
|
|
@ -375,8 +394,12 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
|||
{
|
||||
// decal has to be clipped at the bottom
|
||||
// let texture clamping handle all extreme cases
|
||||
dv[LL].v = (dv[UL].z - bottomleft) / (dv[UL].z - dv[LL].z)*(dv[LL].v - dv[UL].v) + dv[UL].v;
|
||||
dv[LR].v = (dv[UR].z - bottomright) / (dv[UR].z - dv[LR].z)*(dv[LR].v - dv[UR].v) + dv[UR].v;
|
||||
float t0 = (dv[UL].z - bottomleft) / (dv[UL].z - dv[LL].z);
|
||||
float t1 = (dv[UR].z - bottomright) / (dv[UR].z - dv[LR].z);
|
||||
dv[LL].v = t0 * (dv[LL].v - dv[UL].v) + dv[UL].v;
|
||||
dv[LR].v = t1 * (dv[LR].v - dv[UR].v) + dv[UR].v;
|
||||
dv[LL].lv = mix(dv[UL].lv, dv[LL].lv, t0);
|
||||
dv[LR].lv = mix(dv[UR].lv, dv[LR].lv, t1);
|
||||
dv[LL].z = bottomleft;
|
||||
dv[LR].z = bottomright;
|
||||
}
|
||||
|
|
@ -427,7 +450,7 @@ void HWWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
|||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
|
||||
verts.first[i].Set(dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v, dv[i].lu, dv[i].lv, dv[i].lindex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ struct DecalVertex
|
|||
{
|
||||
float x, y, z;
|
||||
float u, v;
|
||||
float lu, lv, lindex;
|
||||
};
|
||||
|
||||
struct HWDecal
|
||||
|
|
@ -433,7 +434,6 @@ inline float Dist2(float x1,float y1,float x2,float y2)
|
|||
|
||||
bool hw_SetPlaneTextureRotation(const HWSectorPlane * secplane, FGameTexture * gltexture, VSMatrix &mat);
|
||||
void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata);
|
||||
LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z);
|
||||
|
||||
extern const float LARGE_VALUE;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,59 +46,17 @@ T smoothstep(const T edge0, const T edge1, const T x)
|
|||
return t * t * (3.0 - 2.0 * t);
|
||||
}
|
||||
|
||||
LightProbe* FindLightProbe(FLevelLocals* level, float x, float y, float z)
|
||||
static bool TraceLightVisbility(FLightNode* node, const FVector3& L, float dist)
|
||||
{
|
||||
LightProbe* foundprobe = nullptr;
|
||||
if (level->LightProbes.Size() > 0)
|
||||
{
|
||||
#if 1
|
||||
double rcpCellSize = 1.0 / level->LPCellSize;
|
||||
int gridCenterX = (int)std::floor(x * rcpCellSize) - level->LPMinX;
|
||||
int gridCenterY = (int)std::floor(y * rcpCellSize) - level->LPMinY;
|
||||
int gridWidth = level->LPWidth;
|
||||
int gridHeight = level->LPHeight;
|
||||
float lastdist = 0.0f;
|
||||
for (int gridY = gridCenterY - 1; gridY <= gridCenterY + 1; gridY++)
|
||||
{
|
||||
for (int gridX = gridCenterX - 1; gridX <= gridCenterX + 1; gridX++)
|
||||
{
|
||||
if (gridX >= 0 && gridY >= 0 && gridX < gridWidth && gridY < gridHeight)
|
||||
{
|
||||
const LightProbeCell& cell = level->LPCells[gridX + (size_t)gridY * gridWidth];
|
||||
for (int i = 0; i < cell.NumProbes; i++)
|
||||
{
|
||||
LightProbe* probe = cell.FirstProbe + i;
|
||||
float dx = probe->X - x;
|
||||
float dy = probe->Y - y;
|
||||
float dz = probe->Z - z;
|
||||
float dist = dx * dx + dy * dy + dz * dz;
|
||||
if (!foundprobe || dist < lastdist)
|
||||
{
|
||||
foundprobe = probe;
|
||||
lastdist = dist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
float lastdist = 0.0f;
|
||||
for (unsigned int i = 0; i < level->LightProbes.Size(); i++)
|
||||
{
|
||||
LightProbe *probe = &level->LightProbes[i];
|
||||
float dx = probe->X - x;
|
||||
float dy = probe->Y - y;
|
||||
float dz = probe->Z - z;
|
||||
float dist = dx * dx + dy * dy + dz * dz;
|
||||
if (i == 0 || dist < lastdist)
|
||||
{
|
||||
foundprobe = probe;
|
||||
lastdist = dist;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return foundprobe;
|
||||
FDynamicLight* light = node->lightsource;
|
||||
if (!light->Trace() || !level.levelMesh)
|
||||
return true;
|
||||
|
||||
// Note: this is not thread safe (modifies validcount and calls other setup functions)
|
||||
// FTraceResults results;
|
||||
// return !Trace(light->Pos, light->Sector, DVector3(-L.X, -L.Y, -L.Z), dist, 0, ML_BLOCKING, nullptr, results);
|
||||
|
||||
return level.levelMesh->Trace(FVector3((float)light->Pos.X, (float)light->Pos.Y, (float)light->Pos.Z), FVector3(-L.X, -L.Y, -L.Z), dist);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
@ -115,14 +73,6 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig
|
|||
|
||||
out[0] = out[1] = out[2] = 0.f;
|
||||
|
||||
LightProbe* probe = FindLightProbe(Level, x, y, z);
|
||||
if (probe)
|
||||
{
|
||||
out[0] = probe->Red;
|
||||
out[1] = probe->Green;
|
||||
out[2] = probe->Blue;
|
||||
}
|
||||
|
||||
// Go through both light lists
|
||||
while (node)
|
||||
{
|
||||
|
|
@ -156,38 +106,43 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FLig
|
|||
{
|
||||
dist = sqrtf(dist); // only calculate the square root if we really need it.
|
||||
|
||||
frac = 1.0f - (dist / radius);
|
||||
|
||||
if (light->IsSpot())
|
||||
{
|
||||
if (light->IsSpot() || light->Trace())
|
||||
L *= -1.0f / dist;
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xyLen = negPitch.Cos();
|
||||
double spotDirX = -Angle.Cos() * xyLen;
|
||||
double spotDirY = -Angle.Sin() * xyLen;
|
||||
double spotDirZ = -negPitch.Sin();
|
||||
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
|
||||
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
|
||||
}
|
||||
|
||||
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z }))))
|
||||
if (TraceLightVisbility(node, L, dist))
|
||||
{
|
||||
lr = light->GetRed() / 255.0f;
|
||||
lg = light->GetGreen() / 255.0f;
|
||||
lb = light->GetBlue() / 255.0f;
|
||||
if (light->IsSubtractive())
|
||||
frac = 1.0f - (dist / radius);
|
||||
|
||||
if (light->IsSpot())
|
||||
{
|
||||
float bright = (float)FVector3(lr, lg, lb).Length();
|
||||
FVector3 lightColor(lr, lg, lb);
|
||||
lr = (bright - lr) * -1;
|
||||
lg = (bright - lg) * -1;
|
||||
lb = (bright - lb) * -1;
|
||||
DAngle negPitch = -*light->pPitch;
|
||||
DAngle Angle = light->target->Angles.Yaw;
|
||||
double xyLen = negPitch.Cos();
|
||||
double spotDirX = -Angle.Cos() * xyLen;
|
||||
double spotDirY = -Angle.Sin() * xyLen;
|
||||
double spotDirZ = -negPitch.Sin();
|
||||
double cosDir = L.X * spotDirX + L.Y * spotDirY + L.Z * spotDirZ;
|
||||
frac *= (float)smoothstep(light->pSpotOuterAngle->Cos(), light->pSpotInnerAngle->Cos(), cosDir);
|
||||
}
|
||||
|
||||
out[0] += lr * frac;
|
||||
out[1] += lg * frac;
|
||||
out[2] += lb * frac;
|
||||
if (frac > 0 && (!light->shadowmapped || (light->GetRadius() > 0 && screen->mShadowMap.ShadowTest(light->Pos, { x, y, z }))))
|
||||
{
|
||||
lr = light->GetRed() / 255.0f;
|
||||
lg = light->GetGreen() / 255.0f;
|
||||
lb = light->GetBlue() / 255.0f;
|
||||
if (light->IsSubtractive())
|
||||
{
|
||||
float bright = (float)FVector3(lr, lg, lb).Length();
|
||||
FVector3 lightColor(lr, lg, lb);
|
||||
lr = (bright - lr) * -1;
|
||||
lg = (bright - lg) * -1;
|
||||
lb = (bright - lb) * -1;
|
||||
}
|
||||
|
||||
out[0] += lr * frac;
|
||||
out[1] += lg * frac;
|
||||
out[2] += lb * frac;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -249,7 +204,16 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata)
|
|||
{
|
||||
if (std::find(addedLights.begin(), addedLights.end(), light) == addedLights.end()) // Check if we already added this light from a different subsector
|
||||
{
|
||||
AddLightToList(modellightdata, group, light, true);
|
||||
FVector3 L(dx, dy, dz);
|
||||
float dist = sqrtf(distSquared);
|
||||
if (light->Trace())
|
||||
L *= 1.0f / dist;
|
||||
|
||||
if (TraceLightVisbility(node, L, dist))
|
||||
{
|
||||
AddLightToList(modellightdata, group, light, true);
|
||||
}
|
||||
|
||||
addedLights.Push(light);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,16 +295,10 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (actor && di->Level->LightProbes.Size() > 0)
|
||||
{
|
||||
LightProbe* probe = FindLightProbe(di->Level, actor->X(), actor->Y(), actor->Center());
|
||||
if (probe)
|
||||
state.SetDynLight(probe->Red, probe->Green, probe->Blue);
|
||||
}
|
||||
|
||||
FHWModelRenderer renderer(di, state, dynlightindex);
|
||||
RenderModel(&renderer, x, y, z, modelframe, actor, di->Viewpoint.TicFrac);
|
||||
state.SetVertexBuffer(screen->mVertexData);
|
||||
state.SetLightIndex(-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -761,13 +761,6 @@ void HWDrawInfo::PreparePlayerSprites3D(sector_t * viewsector, area_t in_area)
|
|||
{
|
||||
hw_GetDynModelLight(playermo, lightdata);
|
||||
hudsprite.lightindex = screen->mLights->UploadLights(lightdata);
|
||||
LightProbe* probe = FindLightProbe(playermo->Level, playermo->X(), playermo->Y(), playermo->Center());
|
||||
if (probe)
|
||||
{
|
||||
hudsprite.dynrgb[0] = probe->Red;
|
||||
hudsprite.dynrgb[1] = probe->Green;
|
||||
hudsprite.dynrgb[2] = probe->Blue;
|
||||
}
|
||||
}
|
||||
|
||||
// [BB] In the HUD model step we just render the model and break out.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue