Skip to content

Commit ffba4fb

Browse files
committed
2 parents bef780c + 1701eb2 commit ffba4fb

26 files changed

+584
-8
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Numerics;
2+
using RayTracer.Core;
3+
using RayTracer.Core.Scenes;
4+
using Microsoft.VisualStudio.TestTools.UnitTesting;
5+
6+
namespace RayTracer.Core.Tests
7+
{
8+
[TestClass]
9+
public class CameraOptionsTests
10+
{
11+
[TestMethod]
12+
public void Engine_Uses_RenderOptions_CameraTarget_When_Set()
13+
{
14+
var scene = new SphereScene();
15+
var options = new RenderOptions
16+
{
17+
Width = 100,
18+
Height = 80,
19+
CameraPosition = new Vector3(0,0,-5),
20+
CameraTarget = new Vector3(10,10,10),
21+
TraceDepth = 1,
22+
DisableReflections = true
23+
};
24+
25+
var engine = new Engine(scene, options);
26+
var img = engine.Render();
27+
Assert.AreEqual(options.Width, img.Width);
28+
Assert.AreEqual(options.Height, img.Height);
29+
}
30+
}
31+
}

RayTracer.Core/Engine.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public Image<Rgba32> Render()
6666

6767
// Camera basis using CameraPosition and CameraTarget/Scene Camera Target
6868
Vector3 camPos = _scene.Camera.Position;
69-
Vector3 camTarget = _scene.Camera.Target.HasValue ? _scene.Camera.Target.Value : _options.CameraTarget;
69+
// Prefer explicit CameraTarget from options when provided (non-zero), otherwise fall back to scene's camera target
70+
Vector3 camTarget = _options.CameraTarget != Vector3.Zero ? _options.CameraTarget : (_scene.Camera.Target.HasValue ? _scene.Camera.Target.Value : Vector3.Zero);
7071
Vector3 camForward = Vector3.Normalize(camTarget - camPos);
7172
if (camForward == Vector3.Zero) camForward = Vector3.UnitZ;
7273
Vector3 worldUp = Vector3.UnitY;

RayTracer.Core/RayTracer.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net10.0</TargetFramework>
4+
<TargetFramework>net8.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
</PropertyGroup>
77

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System.Numerics;
2+
using RayTracer.Core.Materials;
3+
using RayTracer.Core.Primitives;
4+
5+
namespace RayTracer.Core.Scenes;
6+
7+
public class ReflectiveSphereScene : Scene
8+
{
9+
public ReflectiveSphereScene()
10+
{
11+
// Ground plane
12+
AddObject(new Primitives.Plane(new Vector3(0, 1, 0), 1000, new Material(new Vector3(0.12f, 0.12f, 0.12f), diffuse: 0.9f, reflection: 0.15f, specular: 0.2f), null));
13+
14+
// Arrange ~10 spheres in a loose cluster to showcase reflections
15+
var center = new Vector3(0f, 0.6f, 8f);
16+
var positions = new Vector3[] {
17+
new Vector3( -3.0f, 0.45f, 7.5f),
18+
new Vector3( -1.6f, 0.6f, 8.8f),
19+
new Vector3( -0.2f, 0.5f, 7.3f),
20+
new Vector3( 1.2f, 0.55f, 8.1f),
21+
new Vector3( 2.6f, 0.4f, 7.8f),
22+
new Vector3( 0.0f, 1.2f, 9.2f),
23+
new Vector3( -2.4f, 1.0f, 9.6f),
24+
new Vector3( 2.0f, 1.1f, 9.9f),
25+
new Vector3( -0.8f, 0.9f, 10.6f),
26+
new Vector3( 1.6f, 0.75f, 11.0f)
27+
};
28+
29+
float[] radii = new float[] { 0.45f, 0.6f, 0.4f, 0.5f, 0.35f, 0.85f, 0.7f, 0.6f, 0.55f, 0.65f };
30+
31+
// Create reflective materials with slight variation in tint
32+
for (int i = 0; i < positions.Length; i++)
33+
{
34+
var pos = positions[i];
35+
var radius = radii[i % radii.Length];
36+
var tint = new Vector3(
37+
0.3f + 0.6f * (i % 3 == 0 ? 1f : 0.6f),
38+
0.25f + 0.5f * ((i + 1) % 3 == 0 ? 1f : 0.45f),
39+
0.2f + 0.7f * ((i + 2) % 3 == 0 ? 1f : 0.5f)
40+
);
41+
42+
var mat = new Material(tint, diffuse: 0.08f, reflection: 0.92f, specular: 1f);
43+
AddObject(new Sphere(pos, radius, mat, null));
44+
}
45+
46+
// A few semi-matte spheres to add contrast
47+
AddObject(new Sphere(new Vector3(-4.2f, 0.5f, 9.0f), 0.6f, new Material(new Vector3(0.15f,0.18f,0.25f), diffuse: 0.7f, reflection: 0.05f, specular: 0.15f), null));
48+
AddObject(new Sphere(new Vector3(4.0f, 0.6f, 8.6f), 0.7f, new Material(new Vector3(0.9f,0.85f,0.7f), diffuse: 0.6f, reflection: 0.1f, specular: 0.2f), null));
49+
50+
// Lights: soft key and fill lights to produce visible reflections/highlights
51+
AddLight(new Light(new Vector3(4f, 8f, -6f), float.MinValue, new Material(new Vector3(1f, 0.98f, 0.95f))));
52+
AddLight(new Light(new Vector3(-6f, 6f, -4f), float.MinValue, new Material(new Vector3(0.8f, 0.9f, 1f))));
53+
AddLight(new Light(new Vector3(0f, 10f, 6f), float.MinValue, new Material(new Vector3(0.6f, 0.6f, 0.7f))));
54+
55+
// Camera target
56+
Camera.Target = center;
57+
}
58+
}

RayTracer.Windows/App.xaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Application
3+
x:Class="RayTracer.Windows.App"
4+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6+
xmlns:local="using:RayTracer.Windows">
7+
<Application.Resources>
8+
<ResourceDictionary>
9+
<ResourceDictionary.MergedDictionaries>
10+
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
11+
<!-- Other merged dictionaries here -->
12+
</ResourceDictionary.MergedDictionaries>
13+
<!-- Other app resources here -->
14+
</ResourceDictionary>
15+
</Application.Resources>
16+
</Application>

RayTracer.Windows/App.xaml.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using Microsoft.UI.Xaml;
2+
using Microsoft.UI.Xaml.Controls;
3+
using Microsoft.UI.Xaml.Controls.Primitives;
4+
using Microsoft.UI.Xaml.Data;
5+
using Microsoft.UI.Xaml.Input;
6+
using Microsoft.UI.Xaml.Media;
7+
using Microsoft.UI.Xaml.Navigation;
8+
using Microsoft.UI.Xaml.Shapes;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.IO;
12+
using System.Linq;
13+
using System.Runtime.InteropServices.WindowsRuntime;
14+
using Windows.ApplicationModel;
15+
using Windows.ApplicationModel.Activation;
16+
using Windows.Foundation;
17+
using Windows.Foundation.Collections;
18+
19+
// To learn more about WinUI, the WinUI project structure,
20+
// and more about our project templates, see: http://aka.ms/winui-project-info.
21+
22+
namespace RayTracer.Windows
23+
{
24+
/// <summary>
25+
/// Provides application-specific behavior to supplement the default Application class.
26+
/// </summary>
27+
public partial class App : Application
28+
{
29+
private Window? _window;
30+
31+
/// <summary>
32+
/// Initializes the singleton application object. This is the first line of authored code
33+
/// executed, and as such is the logical equivalent of main() or WinMain().
34+
/// </summary>
35+
public App()
36+
{
37+
InitializeComponent();
38+
}
39+
40+
/// <summary>
41+
/// Invoked when the application is launched.
42+
/// </summary>
43+
/// <param name="args">Details about the launch request and process.</param>
44+
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
45+
{
46+
_window = new MainWindow();
47+
_window.Activate();
48+
}
49+
}
50+
}
432 Bytes
Loading
5.25 KB
Loading
1.71 KB
Loading
637 Bytes
Loading

0 commit comments

Comments
 (0)