Add fake quad lighting (multisampling)
This commit is contained in:
parent
fdc84a0d81
commit
ba31c21b0d
|
@ -10,6 +10,7 @@ public class Light
|
||||||
public float InnerRadius;
|
public float InnerRadius;
|
||||||
public float Radius;
|
public float Radius;
|
||||||
public float R2;
|
public float R2;
|
||||||
|
public bool QuadLit;
|
||||||
|
|
||||||
public bool Spotlight;
|
public bool Spotlight;
|
||||||
public Vector3 SpotlightDir;
|
public Vector3 SpotlightDir;
|
||||||
|
|
|
@ -232,6 +232,11 @@ class Program
|
||||||
|
|
||||||
if (propLight != null)
|
if (propLight != null)
|
||||||
{
|
{
|
||||||
|
if (propLight.QuadLit)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Quadlit light wowzer");
|
||||||
|
}
|
||||||
|
|
||||||
var light = new Light
|
var light = new Light
|
||||||
{
|
{
|
||||||
Position = baseLight.Position + propLight.Offset,
|
Position = baseLight.Position + propLight.Offset,
|
||||||
|
@ -239,6 +244,7 @@ class Program
|
||||||
InnerRadius = propLight.InnerRadius,
|
InnerRadius = propLight.InnerRadius,
|
||||||
Radius = propLight.Radius,
|
Radius = propLight.Radius,
|
||||||
R2 = propLight.Radius * propLight.Radius,
|
R2 = propLight.Radius * propLight.Radius,
|
||||||
|
QuadLit = propLight.QuadLit,
|
||||||
Spotlight = baseLight.Spotlight,
|
Spotlight = baseLight.Spotlight,
|
||||||
SpotlightDir = baseLight.SpotlightDir,
|
SpotlightDir = baseLight.SpotlightDir,
|
||||||
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
||||||
|
@ -267,6 +273,7 @@ class Program
|
||||||
InnerRadius = propAnimLight.InnerRadius,
|
InnerRadius = propAnimLight.InnerRadius,
|
||||||
Radius = propAnimLight.Radius,
|
Radius = propAnimLight.Radius,
|
||||||
R2 = propAnimLight.Radius * propAnimLight.Radius,
|
R2 = propAnimLight.Radius * propAnimLight.Radius,
|
||||||
|
QuadLit = propAnimLight.QuadLit,
|
||||||
Spotlight = baseLight.Spotlight,
|
Spotlight = baseLight.Spotlight,
|
||||||
SpotlightDir = baseLight.SpotlightDir,
|
SpotlightDir = baseLight.SpotlightDir,
|
||||||
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
||||||
|
@ -449,44 +456,26 @@ class Program
|
||||||
var pos = topLeft;
|
var pos = topLeft;
|
||||||
pos += x * 0.25f * renderPoly.TextureVectors.Item1;
|
pos += x * 0.25f * renderPoly.TextureVectors.Item1;
|
||||||
pos += y * 0.25f * renderPoly.TextureVectors.Item2;
|
pos += y * 0.25f * renderPoly.TextureVectors.Item2;
|
||||||
|
|
||||||
// Embree has robustness issues when hitting poly edges which
|
var hit = false;
|
||||||
// results in false misses. To alleviate this we pre-push everything
|
var strength = 0f;
|
||||||
// slightly towards the center of the poly.
|
|
||||||
var centerOffset = renderPoly.Center - pos;
|
// TODO: THIS IS ACTUALLY MULTISAMPLING NOT QUAD LIGHTING
|
||||||
if (centerOffset.LengthSquared() > MathUtils.Epsilon)
|
if (light.QuadLit)
|
||||||
{
|
{
|
||||||
pos += Vector3.Normalize(centerOffset) * MathUtils.Epsilon;
|
var xOffset = 0.25f * 0.25f * renderPoly.TextureVectors.Item1;
|
||||||
|
var yOffset = 0.25f * 0.25f * renderPoly.TextureVectors.Item2;
|
||||||
|
hit |= TracePixel(scene, light, pos - xOffset - yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
|
||||||
|
hit |= TracePixel(scene, light, pos + xOffset - yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
|
||||||
|
hit |= TracePixel(scene, light, pos - xOffset + yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
|
||||||
|
hit |= TracePixel(scene, light, pos + xOffset + yOffset, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
|
||||||
|
strength /= 4f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hit |= TracePixel(scene, light, pos, renderPoly.Center, plane, planeMapper, v2ds, ref strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't see our target point from the center of the poly
|
|
||||||
// then it's outside the world. We need to clip the point to slightly
|
|
||||||
// inside the poly and retrace to avoid three problems:
|
|
||||||
// 1. Darkened spots from lightmap pixels whose center is outside
|
|
||||||
// the polygon but is partially contained in the polygon
|
|
||||||
// 2. Darkened spots from linear filtering of points outside the
|
|
||||||
// polygon which have missed
|
|
||||||
// 3. Darkened spots where centers are on the exact edge of a poly
|
|
||||||
// which can sometimes cause Embree to miss casts
|
|
||||||
var inPoly = TraceRay(scene, renderPoly.Center + plane.Normal * 0.25f, pos);
|
|
||||||
if (!inPoly)
|
|
||||||
{
|
|
||||||
var p2d = planeMapper.MapTo2d(pos);
|
|
||||||
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
|
|
||||||
pos = planeMapper.MapTo3d(p2d);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're out of range there's no point casting a ray
|
|
||||||
// There's probably a better way to discard the entire lightmap
|
|
||||||
// if we're massively out of range
|
|
||||||
if ((pos - light.Position).LengthSquared() > light.R2)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We cast from the light to the pixel because the light has
|
|
||||||
// no mesh in the scene to hit
|
|
||||||
var hit = TraceRay(scene, light.Position, pos);
|
|
||||||
if (hit)
|
if (hit)
|
||||||
{
|
{
|
||||||
// If we're an anim light there's a lot of stuff we need to update
|
// If we're an anim light there's a lot of stuff we need to update
|
||||||
|
@ -506,7 +495,6 @@ class Program
|
||||||
info.AnimLightBitmask |= 1u << paletteIdx;
|
info.AnimLightBitmask |= 1u << paletteIdx;
|
||||||
layer = paletteIdx + 1;
|
layer = paletteIdx + 1;
|
||||||
}
|
}
|
||||||
var strength = light.StrengthAtPoint(pos, plane);
|
|
||||||
lightmap.AddLight(layer, x, y, light.Color, strength, hdr);
|
lightmap.AddLight(layer, x, y, light.Color, strength, hdr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,6 +505,60 @@ class Program
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TracePixel(
|
||||||
|
Raytracer scene,
|
||||||
|
Light light,
|
||||||
|
Vector3 pos,
|
||||||
|
Vector3 polyCenter,
|
||||||
|
Plane plane,
|
||||||
|
MathUtils.PlanePointMapper planeMapper,
|
||||||
|
Vector2[] v2ds,
|
||||||
|
ref float strength)
|
||||||
|
{
|
||||||
|
// Embree has robustness issues when hitting poly edges which
|
||||||
|
// results in false misses. To alleviate this we pre-push everything
|
||||||
|
// slightly towards the center of the poly.
|
||||||
|
var centerOffset = polyCenter - pos;
|
||||||
|
if (centerOffset.LengthSquared() > MathUtils.Epsilon)
|
||||||
|
{
|
||||||
|
pos += Vector3.Normalize(centerOffset) * MathUtils.Epsilon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we can't see our target point from the center of the poly
|
||||||
|
// then it's outside the world. We need to clip the point to slightly
|
||||||
|
// inside the poly and retrace to avoid three problems:
|
||||||
|
// 1. Darkened spots from lightmap pixels whose center is outside
|
||||||
|
// the polygon but is partially contained in the polygon
|
||||||
|
// 2. Darkened spots from linear filtering of points outside the
|
||||||
|
// polygon which have missed
|
||||||
|
// 3. Darkened spots where centers are on the exact edge of a poly
|
||||||
|
// which can sometimes cause Embree to miss casts
|
||||||
|
var inPoly = TraceRay(scene, polyCenter + plane.Normal * 0.25f, pos);
|
||||||
|
if (!inPoly)
|
||||||
|
{
|
||||||
|
var p2d = planeMapper.MapTo2d(pos);
|
||||||
|
p2d = MathUtils.ClipPointToPoly2d(p2d, v2ds);
|
||||||
|
pos = planeMapper.MapTo3d(p2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're out of range there's no point casting a ray
|
||||||
|
// There's probably a better way to discard the entire lightmap
|
||||||
|
// if we're massively out of range
|
||||||
|
if ((pos - light.Position).LengthSquared() > light.R2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We cast from the light to the pixel because the light has
|
||||||
|
// no mesh in the scene to hit
|
||||||
|
var hit = TraceRay(scene, light.Position, pos);
|
||||||
|
if (hit)
|
||||||
|
{
|
||||||
|
strength += light.StrengthAtPoint(pos, plane);
|
||||||
|
}
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TraceRay(Raytracer scene, Vector3 origin, Vector3 target)
|
private static bool TraceRay(Raytracer scene, Vector3 origin, Vector3 target)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue