Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Initial extraction of scalar rt math #88

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 6 additions & 102 deletions src/Raytracer/BaseRayTracer.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using Raytracer.Geometry.Base.Geometries;
using Raytracer.Geometry.Base.Hitable;
using Raytracer.Geometry.Base.Models;
using Raytracer.Geometry.Base.Models;
using Raytracer.Geometry.Scenes;
using Raytracer.Geometry.Utils;
using Raytracer.Math;

namespace Raytracer
{
Expand All @@ -26,101 +24,6 @@ int width
_halfWidth = _width / 2.0f;
}

private Optional<Intersection> Intersect(in Ray ray, in MyScene scene)
{
var closestDist = float.MaxValue;
var closestInter = new Optional<Intersection>();

foreach (var thing in scene.Things)
{
var inter = thing.Intersect(ray);
if (inter.HasValue && inter.Value.Distance < closestDist)
{
closestDist = inter.Value.Distance;
closestInter = inter;
}
}

return closestInter;
}

private Optional<float> TestRay(in Ray ray, MyScene scene)
{
var intersection = Intersect(ray, scene);
return intersection.HasValue
? new Optional<float>(intersection.Value.Distance)
: new Optional<float>();
}

private Color TraceRay(in Ray ray, MyScene scene, int depth)
{
var intersection = Intersect(ray, scene);
return intersection.HasValue
? Shade(intersection.Value, scene, depth)
: Color.Background;
}

private const int MaxDepth = 5;

private Color Shade(in Intersection intersection, MyScene scene, int depth)
{
var d = intersection.Ray.Direction;
var pos = (intersection.Distance * d) + intersection.Ray.Start;
var normal = intersection.Thing.Normal(pos);
var reflectDir = d - (2.0f * GeometryMath.Dot(normal, d) * normal);
var naturalColor = Color.Background + NaturalColor(intersection.Thing, pos, normal, reflectDir, scene);
var reflectedColor = depth >= MaxDepth
? Color.Gray
: ReflectionColor(intersection.Thing, pos, reflectDir, scene, depth);
return naturalColor + reflectedColor;
}

private Color ReflectionColor(IHitable thing, in Vec3 pos, in Vec3 rd, MyScene scene, int depth)
{
return GeometryMath.Scale(
thing.Surface.Reflect(pos),
TraceRay(new Ray(pos, rd), scene, depth + 1)
);
}

private Color AddLight(IHitable thing, in Vec3 pos, in Vec3 normal, in Vec3 rayDir, MyScene scene, Color col,
Light light)
{
var lightDir = light.Position - pos;
var lightDirNorm = GeometryMath.Norm(lightDir);
var nearIntersection = TestRay(new Ray(pos, lightDirNorm), scene);
var isInShadow = nearIntersection.HasValue && nearIntersection.Value < GeometryMath.Mag(lightDir);
if (isInShadow) return col;

var illumination = GeometryMath.Dot(lightDirNorm, normal);
var lightColor = illumination > 0.0f
? GeometryMath.Scale(illumination, light.Color)
: Color.DefaultColor;
var specular = GeometryMath.Dot(lightDirNorm, GeometryMath.Norm(rayDir));
var surf = thing.Surface;
var specularColor = specular > 0.0f
? GeometryMath.Scale(GeometryMath.Pow(specular, surf.Roughness), light.Color)
: Color.DefaultColor;

return col + (surf.Diffuse(pos) * lightColor + surf.Specular(pos) * specularColor);
}

private Color NaturalColor(IHitable thing, in Vec3 pos, in Vec3 norm, in Vec3 rd, MyScene scene)
{
var col = Color.DefaultColor;
foreach (var light in scene.Lights)
col = AddLight(thing, pos, norm, rd, scene, col, light);
return col;
}

private Vec3 Point(int x, int y, in Camera cam)
{
var recenterX = (x - _halfWidth) / 2.0f / _width;
var recenterY = -(y - _halfHeight) / 2.0f / _height;

return GeometryMath.Norm(cam.Forward + (recenterX * cam.Right + recenterY * cam.Up));
}

public Canvas.Canvas Render(MyScene scene)
{
var canvas = new Canvas.Canvas(_width, _height);
Expand All @@ -129,13 +32,14 @@ public Canvas.Canvas Render(MyScene scene)
{
for (int x = 0; x < _width; x++)
{
var point = Point(x, y, scene.Camera);
var color = TraceRay(new Ray(scene.Camera.Position, point), scene, 0);
var point = ScalarRayTracerMath.Point(
x, y, _width, _height, _halfWidth, _halfHeight, scene.Camera);
var color = ScalarRayTracerMath.TraceRay(new Ray(scene.Camera.Position, point), scene, 0);
canvas[x, y] = color;
}
}

return canvas;
}
}
}
}
117 changes: 117 additions & 0 deletions src/Raytracer/Math/ScalarRayTracerMath.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System.Runtime.CompilerServices;
using Raytracer.Geometry.Base.Geometries;
using Raytracer.Geometry.Base.Hitable;
using Raytracer.Geometry.Base.Models;
using Raytracer.Geometry.Scenes;
using Raytracer.Geometry.Utils;

namespace Raytracer.Math
{
public static class ScalarRayTracerMath
{
public const int MaxDepth = 5;

[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static Vec3 Point(
in int x,
in int y,
in float width,
in float height,
in float halfWidth,
in float halfHeight,
Comment on lines +20 to +21
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nie wiem czy dzielenie przez 2 jest tutaj tak kosztowne, żeby to przesyłać wyliczone... wysyłałbym tylko width i height

in Camera cam)
{
var recenterX = (x - halfWidth) / 2.0f / width;
var recenterY = -(y - halfHeight) / 2.0f / height;

return GeometryMath.Norm(cam.Forward + (recenterX * cam.Right + recenterY * cam.Up));
}

public static Optional<Intersection> Intersect(in Ray ray, in MyScene scene)
{
var closestDist = float.MaxValue;
var closestInter = new Optional<Intersection>();

foreach (var thing in scene.Things)
{
var inter = thing.Intersect(ray);
if (inter.HasValue && inter.Value.Distance < closestDist)
{
closestDist = inter.Value.Distance;
closestInter = inter;
}
}

return closestInter;
}

public static Optional<float> TestRay(in Ray ray, MyScene scene)
{
var intersection = Intersect(ray, scene);
return intersection.HasValue
? new Optional<float>(intersection.Value.Distance)
: new Optional<float>();
}

public static Color TraceRay(in Ray ray, MyScene scene, int depth)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To publiczne zostawiłbym + point, reszta private ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jak nie będą potrzebne to można

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, to zrobię #87 i zobaczymy

{
var intersection = Intersect(ray, scene);
return intersection.HasValue
? Shade(intersection.Value, scene, depth)
: Color.Background;
}


public static Color Shade(in Intersection intersection, MyScene scene, int depth)
{
var d = intersection.Ray.Direction;
var pos = (intersection.Distance * d) + intersection.Ray.Start;
var normal = intersection.Thing.Normal(pos);
var reflectDir = d - (2.0f * GeometryMath.Dot(normal, d) * normal);
var naturalColor = Color.Background + NaturalColor(intersection.Thing, pos, normal, reflectDir, scene);
var reflectedColor = depth >= MaxDepth
? Color.Gray
: ReflectionColor(intersection.Thing, pos, reflectDir, scene, depth);
return naturalColor + reflectedColor;
}

public static Color ReflectionColor(IHitable thing, in Vec3 pos, in Vec3 rd, MyScene scene, int depth)
{
return GeometryMath.Scale(
thing.Surface.Reflect(pos),
TraceRay(new Ray(pos, rd), scene, depth + 1)
);
}

public static Color AddLight(IHitable thing, in Vec3 pos, in Vec3 normal, in Vec3 rayDir, MyScene scene,
Color col,
Light light)
{
var lightDir = light.Position - pos;
var lightDirNorm = GeometryMath.Norm(lightDir);
var nearIntersection = TestRay(new Ray(pos, lightDirNorm), scene);
var isInShadow = nearIntersection.HasValue && nearIntersection.Value < GeometryMath.Mag(lightDir);
if (isInShadow) return col;

var illumination = GeometryMath.Dot(lightDirNorm, normal);
var lightColor = illumination > 0.0f
? GeometryMath.Scale(illumination, light.Color)
: Color.DefaultColor;
var specular = GeometryMath.Dot(lightDirNorm, GeometryMath.Norm(rayDir));
var surf = thing.Surface;
var specularColor = specular > 0.0f
? GeometryMath.Scale(GeometryMath.Pow(specular, surf.Roughness), light.Color)
: Color.DefaultColor;

return col + (surf.Diffuse(pos) * lightColor + surf.Specular(pos) * specularColor);
}

public static Color NaturalColor(IHitable thing, in Vec3 pos, in Vec3 norm, in Vec3 rd, MyScene scene)
{
var col = Color.DefaultColor;
foreach (var light in scene.Lights)
col = AddLight(thing, pos, norm, rd, scene, col, light);
return col;
}
}
}
19 changes: 5 additions & 14 deletions src/Raytracer/RayTracer.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using System.Runtime.Intrinsics;
using Raytracer.Canvas;
using Raytracer.Geometry.Base.Geometries;
using Raytracer.Geometry.Base.Models;
using Raytracer.Geometry.Scenes;
using Raytracer.Geometry.SSE.Extensions;
using Raytracer.Geometry.SSE.Geometries;
using Raytracer.Geometry.SSE.Models;
using Raytracer.Math;

namespace RayTracer
{
Expand All @@ -22,7 +21,7 @@ public class RayTracer
private readonly Vector128<float> _halfWidthVector;

public RayTracer(
int height,
int height,
int width
)
{
Expand All @@ -37,14 +36,6 @@ int width
_halfWidthVector = Vector128.Create(_halfWidth);
}

private Vec3 Point(in int x, in int y, in Camera cam)
{
var recenterX = (x - (_halfWidth)) / 2.0f / _width;
var recenterY = -(y - (_halfHeight)) / 2.0f / _height;

return GeometryMath.Norm(cam.Forward + (recenterX * cam.Right + recenterY * cam.Up));
}

private VecSSE Point(in Vector128<float> x, in Vector128<float> y, in CameraSSE cam)
{
var twosVector = Vector128.Create(2.0f);
Expand Down Expand Up @@ -75,15 +66,15 @@ public Canvas Render(MyScene scene)
for (; x < _width; x += 4)
{
var xVector = Vector128.Create(x, x + 1.0f, x + 2.0f, x + 3.0f);
var yVector = Vector128.Create(1.0f * y);
var yVector = Vector128.Create(1.0f * y);

var pointVector = Point(xVector, yVector, cameraSSE);

}

for (; x < _width; x++)
{
var point = Point(x, y, scene.Camera);
var point = ScalarRayTracerMath.Point(
x, y, _width, _height, _halfWidth, _halfHeight, scene.Camera);
}
}

Expand Down