Skip to content

Commit

Permalink
Start adding color modeling
Browse files Browse the repository at this point in the history
  • Loading branch information
boxofyellow committed Dec 26, 2020
1 parent bf1f933 commit ffdbd90
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 27 deletions.
32 changes: 27 additions & 5 deletions Actors/Actor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,42 @@ public virtual void StartRayRender(Point3D from, LightSource[] sources) {}

public virtual (double DistranceProxy, int Id, Point3D Intersection) RenderRay(Point3D from, Point3D vector, double currentMinDistanceProxy) => default;

public virtual ColorProperties ColorAt(Point3D intersection, int id)
{
const int maxColor = 1 + (int)byte.MaxValue;
const int maxColorValue = maxColor * maxColor;

// emulate plastic
const double diffuse = 0.55;
const double factor = diffuse / (double)maxColor;

int value = id * maxColorValue / s_lastReserved;

double green = (double)(value / maxColor) * factor;
double blue = (double)(value % maxColor) * factor;

// Emulate plastic
return new ColorProperties(
new Point3D(0.0, 0.0, 0.0),
new Point3D(x /*aka Red*/: diffuse, green, blue),
new Point3D(0.7, 0.7, 0.7),
32);
}

public virtual bool DoesItCastShadow(int sourceIndex, Point3D from, Point3D vector, int minId) => false;

// Allows actors to reserve Ids, they will be granted a block count long starting at the returned value
protected static int ReserveIds(int count)
{
lock (s_lockObject)
{
if (int.MaxValue - LastReserved <= count)
if (int.MaxValue - s_lastReserved <= count)
{
throw new OverflowException($"Reserved too many items! {nameof(LastReserved)}:{LastReserved} {nameof(count)}:{count}");
throw new OverflowException($"Reserved too many items! {nameof(s_lastReserved)}:{s_lastReserved} {nameof(count)}:{count}");
}

int result = LastReserved + 1;
LastReserved = result + count;
int result = s_lastReserved + 1;
s_lastReserved = result + count;
return result;
}
}
Expand All @@ -38,6 +60,6 @@ protected static int ReserveIds(int count)
#endif

private static readonly object s_lockObject = new object();
public static int LastReserved {get; private set;} = default; // 0 is reserved for "none"
private static int s_lastReserved = default; // 0 is reserved for "none"
}
}
23 changes: 18 additions & 5 deletions Actors/InfinitePlane.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
using System;

namespace Ascii3dEngine
{
public class InfinitePlane : PolygonActorBase
{
public InfinitePlane(Settings settings, double? x = null, double? y = null, double? z = null)
: base(settings, GetData(x, y, z)) { }
public InfinitePlane(Settings settings, ColorProperties properties, double? x = null, double? y = null, double? z = null)
: base(settings, GetData(x, y, z)) => m_properties = properties;

// Don't Rotate
public override void Act(System.TimeSpan timeDelta, System.TimeSpan elapsedRuntime, Camera camera) {}
public override void Act(System.TimeSpan timeDelta, System.TimeSpan elapsedRuntime, Camera camera) { }

public override ColorProperties ColorAt(Point3D intersection, int id) => m_properties;

private static (Point3D[] Points, int[][] Faces) GetData(double? x, double? y, double? z)
{
int count = (x == null ? 0 : 1)
+ (y == null ? 0 : 1)
+ (z == null ? 0 : 1);

if (count != 1)
{
throw new ArgumentException($"Need to have one, and exactly one plane set, {x}, {y}, {z}");
}

// ok so maybe they are not infinite
double min = -Utilities.MaxRange;
double max = Utilities.MaxRange;
Expand Down Expand Up @@ -38,10 +51,10 @@ private static (Point3D[] Points, int[][] Faces) GetData(double? x, double? y, d
z ?? max),
};

System.Console.WriteLine(string.Join(System.Environment.NewLine, points));

int[][] faces = new [] {new [] {0, 1, 2, 3}};
return (points, faces);
}

private readonly ColorProperties m_properties;
}
}
84 changes: 84 additions & 0 deletions Engine/ColorProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System.Runtime.CompilerServices;

namespace Ascii3dEngine
{
public readonly struct ColorProperties
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]

public ColorProperties(Point3D ambient, Point3D diffuse, Point3D specular, double shininess)
{
Ambient = ambient;
Diffuse = diffuse;
Specular = specular;
Shininess = shininess;
}

public readonly Point3D Ambient;
public readonly Point3D Diffuse;
public readonly Point3D Specular;
public readonly double Shininess;

// From 423, but here are some more. https://www.barradeau.com/nicoptere/dump/materials.html
public static ColorProperties BlackPlastic = new ColorProperties(
new Point3D(0.0, 0.0, 0.0),
new Point3D(0.01, 0.01, 0.01),
new Point3D(0.5, 0.5, 0.5),
32);

public static ColorProperties Brass = new ColorProperties(
new Point3D(0.329412, 0.223529, 0.027451),
new Point3D(0.780392, 0.568627, 0.113725),
new Point3D(0.992157, 0.941176, 0.807843),
27.8974);

public static ColorProperties Bronze = new ColorProperties(
new Point3D(0.2125, 0.1275, 0.054),
new Point3D(0.714, 0.4284, 0.18144),
new Point3D(0.393548, 0.271906, 0.166721),
25.6);

public static ColorProperties Chrome = new ColorProperties(
new Point3D(0.25, 0.25, 0.25),
new Point3D(0.4, 0.4, 0.4),
new Point3D(0.774597, 0.774597, 0.774597),
76.8);

public static ColorProperties Copper = new ColorProperties(
new Point3D(0.19125, 0.0735, 0.0225),
new Point3D(0.7038, 0.27048, 0.828),
new Point3D(0.256777, 0.137622, 0.086014),
12.8);

public static ColorProperties Gold = new ColorProperties(
new Point3D(0.24725, 0.1995, 0.0745),
new Point3D(0.75164, 0.60648, 0.22648),
new Point3D(0.628281, 0.555802, 0.366065),
51.2);

public static ColorProperties Pewter = new ColorProperties(
new Point3D(0.10588, 0.058824, 0.113725),
new Point3D(0.427451, 0.470588, 0.541176),
new Point3D(0.3333, 0.3333, 0.521569),
9.84615);

public static ColorProperties Silver = new ColorProperties(
new Point3D(0.19225, 0.19225, 0.19225),
new Point3D(0.50754, 0.50754, 0.50754),
new Point3D(0.508273, 0.508273, 0.508273),
51.2);

public static ColorProperties PolishedSilver = new ColorProperties(
new Point3D(0.23125, 0.23125, 0.23125),
new Point3D(0.2775, 0.2775, 0.2775),
new Point3D(0.773911, 0.773911, 0.773911),
89.6);

// https://www.sci.tamucc.edu/~sking/Courses/COSC5327/Assignments/Materials.html
public static ColorProperties WhitePlastic = new ColorProperties(
new Point3D(0.0, 0.0, 0.0),
new Point3D(0.55, 0.55, 0.55),
new Point3D(0.7, 0.7, 0.7),
32);
}
}
38 changes: 22 additions & 16 deletions Engine/RayTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,7 @@ public static string[] TraceCharRay(Settings settings, int width, int height, Sc
double minDistanceProxy = double.MaxValue;
int minId = default;
Point3D minIntersection = default;
#if (DEBUG)
Actor minActor = default;
#endif
foreach (Actor actor in actors)
{
Expand All @@ -117,9 +115,7 @@ public static string[] TraceCharRay(Settings settings, int width, int height, Sc
minId = id;
minDistanceProxy = distanceProxy;
minIntersection = intersection;
#if (DEBUG)
minActor = actor;
#endif
}
}
Expand All @@ -134,11 +130,19 @@ public static string[] TraceCharRay(Settings settings, int width, int height, Sc
}
#endif
int value = minId * c_maxColorValue / Actor.LastReserved;
ColorProperties properties = minActor.ColorAt(minIntersection, minId);
int red = byte.MaxValue;
int green = value / c_maxColor;
int blue = value % c_maxColor;
// just for testing lets assume all light intensity are 1.0
// See Page 761
double red = 1.0 * properties.Ambient.X;
double green = 1.0 * properties.Ambient.Y;
double blue = 1.0 * properties.Ambient.Z;
// we should compute Iambert = max(0, (s dot m) / (|s||m|))
red += (0.7 * properties.Diffuse.X);
green += (0.7 * properties.Diffuse.Y);
blue += (0.7 * properties.Diffuse.Z);
for (int i = 0; i < sources.Length; i++)
{
Expand All @@ -155,23 +159,25 @@ public static string[] TraceCharRay(Settings settings, int width, int height, Sc
}
}
if (inShadow)
if (!inShadow)
{
red /= 2;
green /= 2;
blue /= 2;
// we should compute phong = max(0, (h dot m) / (|h||m|))
// Don't for get ^Shininess
red += (0.7 * properties.Specular.X);
green += (0.7 * properties.Specular.Y);
blue += (0.7 * properties.Specular.Z);
}
}
result[x, y] = new Rgb24((byte)red, (byte)green, (byte)blue);
red = Math.Min(1.0, red);
green = Math.Min(1.0, green);
blue = Math.Min(1.0, blue);
result[x, y] = new Rgb24((byte)(red * 255.0), (byte)(green * 255.0), (byte)(blue * 255.0));
}
}
});

return result;
}

private const int c_maxColor = 1 + (int)byte.MaxValue;
private const int c_maxColorValue = c_maxColor * c_maxColor;
}
}
2 changes: 1 addition & 1 deletion Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ private static int Run(Settings settings)
scene.AddActor(new Model(settings));
}

scene.AddActor(new InfinitePlane(settings, y: -30.0));
scene.AddActor(new InfinitePlane(settings, ColorProperties.WhitePlastic, y: -30.0));

scene.AddLightSource(new LightSource(
new Point3D(0, 200, 0),
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
![Teapot with Shadow](docs/teapot_shadow.gif)
![Teapot with Shadow](docs/teapot_color.gif)
Binary file added docs/teapot_color.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ffdbd90

Please sign in to comment.