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 Radius;
|
||||
public float R2;
|
||||
public bool QuadLit;
|
||||
|
||||
public bool Spotlight;
|
||||
public Vector3 SpotlightDir;
|
||||
|
|
|
@ -232,6 +232,11 @@ class Program
|
|||
|
||||
if (propLight != null)
|
||||
{
|
||||
if (propLight.QuadLit)
|
||||
{
|
||||
Console.WriteLine("Quadlit light wowzer");
|
||||
}
|
||||
|
||||
var light = new Light
|
||||
{
|
||||
Position = baseLight.Position + propLight.Offset,
|
||||
|
@ -239,6 +244,7 @@ class Program
|
|||
InnerRadius = propLight.InnerRadius,
|
||||
Radius = propLight.Radius,
|
||||
R2 = propLight.Radius * propLight.Radius,
|
||||
QuadLit = propLight.QuadLit,
|
||||
Spotlight = baseLight.Spotlight,
|
||||
SpotlightDir = baseLight.SpotlightDir,
|
||||
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
||||
|
@ -267,6 +273,7 @@ class Program
|
|||
InnerRadius = propAnimLight.InnerRadius,
|
||||
Radius = propAnimLight.Radius,
|
||||
R2 = propAnimLight.Radius * propAnimLight.Radius,
|
||||
QuadLit = propAnimLight.QuadLit,
|
||||
Spotlight = baseLight.Spotlight,
|
||||
SpotlightDir = baseLight.SpotlightDir,
|
||||
SpotlightInnerAngle = baseLight.SpotlightInnerAngle,
|
||||
|
@ -449,44 +456,26 @@ class Program
|
|||
var pos = topLeft;
|
||||
pos += x * 0.25f * renderPoly.TextureVectors.Item1;
|
||||
pos += y * 0.25f * renderPoly.TextureVectors.Item2;
|
||||
|
||||
// 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 = renderPoly.Center - pos;
|
||||
if (centerOffset.LengthSquared() > MathUtils.Epsilon)
|
||||
|
||||
var hit = false;
|
||||
var strength = 0f;
|
||||
|
||||
// TODO: THIS IS ACTUALLY MULTISAMPLING NOT QUAD LIGHTING
|
||||
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 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;
|
||||
layer = paletteIdx + 1;
|
||||
}
|
||||
var strength = light.StrengthAtPoint(pos, plane);
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue