Add sunlight casting
This commit is contained in:
parent
596ce88215
commit
b34131f3b5
|
@ -8,13 +8,23 @@ namespace KeepersCompound.Lightmapper;
|
||||||
|
|
||||||
public class LightMapper
|
public class LightMapper
|
||||||
{
|
{
|
||||||
private class Settings
|
// The objcast element of sunlight is ignored, we just care if it's quadlit
|
||||||
|
private struct SunSettings
|
||||||
|
{
|
||||||
|
public bool Enabled;
|
||||||
|
public bool QuadLit;
|
||||||
|
public Vector3 Direction;
|
||||||
|
public Vector3 Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct Settings
|
||||||
{
|
{
|
||||||
public Vector3 AmbientLight;
|
public Vector3 AmbientLight;
|
||||||
public bool Hdr;
|
public bool Hdr;
|
||||||
public SoftnessMode MultiSampling;
|
public SoftnessMode MultiSampling;
|
||||||
public float MultiSamplingCenterWeight;
|
public float MultiSamplingCenterWeight;
|
||||||
public bool LightmappedWater;
|
public bool LightmappedWater;
|
||||||
|
public SunSettings Sunlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResourcePathManager.CampaignResources _campaign;
|
private ResourcePathManager.CampaignResources _campaign;
|
||||||
|
@ -58,6 +68,14 @@ public class LightMapper
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sunlightSettings = new SunSettings()
|
||||||
|
{
|
||||||
|
Enabled = rendParams.useSunlight,
|
||||||
|
QuadLit = rendParams.sunlightMode is RendParams.SunlightMode.QuadUnshadowed or RendParams.SunlightMode.QuadObjcastShadows,
|
||||||
|
Direction = rendParams.sunlightDirection,
|
||||||
|
Color = Utils.HsbToRgb(rendParams.sunlightHue, rendParams.sunlightSaturation, rendParams.sunlightBrightness),
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: lmParams LightmappedWater doesn't mean the game will actually *use* the lightmapped water hmm
|
// TODO: lmParams LightmappedWater doesn't mean the game will actually *use* the lightmapped water hmm
|
||||||
var settings = new Settings
|
var settings = new Settings
|
||||||
{
|
{
|
||||||
|
@ -66,6 +84,7 @@ public class LightMapper
|
||||||
MultiSampling = lmParams.ShadowSoftness,
|
MultiSampling = lmParams.ShadowSoftness,
|
||||||
MultiSamplingCenterWeight = lmParams.CenterWeight,
|
MultiSamplingCenterWeight = lmParams.CenterWeight,
|
||||||
LightmappedWater = lmParams.LightmappedWater,
|
LightmappedWater = lmParams.LightmappedWater,
|
||||||
|
Sunlight = sunlightSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
Timing.TimeStage("Gather Lights", BuildLightList);
|
Timing.TimeStage("Gather Lights", BuildLightList);
|
||||||
|
@ -414,6 +433,36 @@ public class LightMapper
|
||||||
var quadTracePoints = settings.MultiSampling == SoftnessMode.HighFourPoint
|
var quadTracePoints = settings.MultiSampling == SoftnessMode.HighFourPoint
|
||||||
? tracePoints
|
? tracePoints
|
||||||
: GetTracePoints(pos, quadOffsets, renderPoly.Center, planeMapper, v2ds);
|
: GetTracePoints(pos, quadOffsets, renderPoly.Center, planeMapper, v2ds);
|
||||||
|
|
||||||
|
// TODO: This isn't quite right yet. It seems to be too bright
|
||||||
|
if (settings.Sunlight.Enabled) {
|
||||||
|
// Check if plane normal is facing towards the light
|
||||||
|
// If it's not then we're never going to be (directly) lit by this
|
||||||
|
// light.
|
||||||
|
var sunAngle = Vector3.Dot(-settings.Sunlight.Direction, plane.Normal);
|
||||||
|
if (sunAngle > 0)
|
||||||
|
{
|
||||||
|
var strength = 0f;
|
||||||
|
var targetPoints = settings.Sunlight.QuadLit ? quadTracePoints : tracePoints;
|
||||||
|
var targetWeights = settings.Sunlight.QuadLit ? quadWeights : weights;
|
||||||
|
for (var idx = 0; idx < targetPoints.Length; idx++)
|
||||||
|
{
|
||||||
|
var point = targetPoints[idx];
|
||||||
|
if (TraceSunRay(point, -settings.Sunlight.Direction))
|
||||||
|
{
|
||||||
|
// Sunlight is a simpler lighting algorithm than normal lights so we can just
|
||||||
|
// do it here
|
||||||
|
strength += targetWeights[idx] * sunAngle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strength != 0f)
|
||||||
|
{
|
||||||
|
lightmap.AddLight(0, x, y, settings.Sunlight.Color, strength, settings.Hdr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var light in _lights)
|
foreach (var light in _lights)
|
||||||
{
|
{
|
||||||
var layer = 0;
|
var layer = 0;
|
||||||
|
@ -596,6 +645,28 @@ public class LightMapper
|
||||||
return Math.Abs(hitDistanceFromTarget) < MathUtils.Epsilon;
|
return Math.Abs(hitDistanceFromTarget) < MathUtils.Epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Can this be merged with the above?
|
||||||
|
private bool TraceSunRay(Vector3 origin, Vector3 direction)
|
||||||
|
{
|
||||||
|
// Avoid self intersection
|
||||||
|
origin += direction * MathUtils.Epsilon;
|
||||||
|
|
||||||
|
var hitSurfaceType = SurfaceType.Water;
|
||||||
|
while (hitSurfaceType == SurfaceType.Water)
|
||||||
|
{
|
||||||
|
var hitResult = _scene.Trace(new Ray
|
||||||
|
{
|
||||||
|
Origin = origin,
|
||||||
|
Direction = Vector3.Normalize(direction),
|
||||||
|
});
|
||||||
|
|
||||||
|
hitSurfaceType = _triangleTypeMap[(int)hitResult.PrimId];
|
||||||
|
origin = hitResult.Position += direction * MathUtils.Epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hitSurfaceType == SurfaceType.Sky;
|
||||||
|
}
|
||||||
|
|
||||||
private void SetAnimLightCellMaps()
|
private void SetAnimLightCellMaps()
|
||||||
{
|
{
|
||||||
if (!_mission.TryGetChunk<PropertyChunk<PropAnimLight>>("P$AnimLight", out var animLightChunk) ||
|
if (!_mission.TryGetChunk<PropertyChunk<PropAnimLight>>("P$AnimLight", out var animLightChunk) ||
|
||||||
|
|
Loading…
Reference in New Issue