-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathSphericalSampling.dib
More file actions
140 lines (109 loc) · 5.11 KB
/
SphericalSampling.dib
File metadata and controls
140 lines (109 loc) · 5.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!meta
{"kernelInfo":{"defaultKernelName":null,"items":[{"name":"csharp","languageName":"C#","aliases":["c#","cs"]},{"name":"fsharp","languageName":"F#","aliases":["f#","fs"]},{"name":"pwsh","languageName":"PowerShell","aliases":["powershell"]},{"name":"javascript","languageName":"JavaScript","aliases":["js"]},{"name":"html","languageName":"HTML"},{"name":"sql","languageName":"SQL"},{"name":"kql","languageName":"KQL"},{"name":"mermaid","languageName":"Mermaid"},{"name":"httpRequest","languageName":"http"},{"name":"value"}]}}
#!csharp
#r "nuget: TinyEmbree"
#r "nuget: SimpleImageIO"
#r "../SeeSharp/bin/Debug/net7.0/SeeSharp.dll"
using SeeSharp;
using SeeSharp.Sampling;
using SeeSharp.Integrators;
using SeeSharp.Experiments;
using SeeSharp.Geometry;
using TinyEmbree;
using SimpleImageIO;
using SimpleImageIO.FlipBook;
using System.Numerics;
using System;
using System.Threading.Tasks;
// Avoids slowing down the Jupyter Kernel with console spam
SeeSharp.Common.ProgressBar.Silent = true;
HTML(FlipBook.MakeHeader()).Display();
#!csharp
SceneRegistry.AddSource("../Data/Scenes");
var sceneConfig = SceneRegistry.LoadScene("CornellBox");
var reference = sceneConfig.GetReferenceImage(512, 512);
var scene = sceneConfig.MakeScene();
scene.FrameBuffer = new(512, 512, "");
scene.Prepare();
#!csharp
abstract class DirectIllum : Integrator {
protected Scene scene;
public DirectIllum(int spp) {
SampleCount = spp;
}
public override void Render(Scene scene) {
this.scene = scene;
for (uint sampleIndex = 0; sampleIndex < SampleCount; ++sampleIndex) {
scene.FrameBuffer.StartIteration();
Parallel.For(0, scene.FrameBuffer.Height, row => {
for (uint col = 0; col < scene.FrameBuffer.Width; ++col) {
uint pixelIndex = (uint)(row * scene.FrameBuffer.Width + col);
RNG rng = new(BaseSeed, pixelIndex, sampleIndex);
RenderPixel((uint)row, col, rng);
}
});
scene.FrameBuffer.EndIteration();
}
}
private void RenderPixel(uint row, uint col, RNG rng) {
var offset = rng.NextFloat2D();
var pixel = new Vector2(col, row) + offset;
var primaryRay = scene.Camera.GenerateRay(pixel, rng).Ray;
var primaryHit = scene.Raytracer.Trace(primaryRay);
if (primaryHit) {
var estimate = EstimateIncidentRadiance(primaryRay, primaryHit, rng);
scene.FrameBuffer.Splat(col, row, estimate);
}
}
protected abstract RgbColor EstimateIncidentRadiance(in Ray ray, in SurfacePoint hit, RNG rng);
}
#!csharp
class UniformArea : DirectIllum {
public UniformArea(int spp) : base(spp) { }
protected override RgbColor EstimateIncidentRadiance(in Ray ray, in SurfacePoint hit, RNG rng) {
// Select a light source
var light = scene.Emitters[rng.NextInt(0, scene.Emitters.Count)];
float lightSelectProb = 1.0f / scene.Emitters.Count;
// Sample a point on the light source
var lightSample = light.SampleUniformArea(rng.NextFloat2D());
Vector3 lightToSurface = Vector3.Normalize(hit.Position - lightSample.Point.Position);
if (!scene.Raytracer.IsOccluded(hit, lightSample.Point)) {
var emission = light.EmittedRadiance(lightSample.Point, lightToSurface);
float jacobian = SampleWarp.SurfaceAreaToSolidAngle(hit, lightSample.Point);
var bsdfCos = hit.Material.EvaluateWithCosine(hit, -ray.Direction, -lightToSurface, false);
var pdf = lightSample.Pdf * lightSelectProb;
return emission / pdf * jacobian * bsdfCos;
}
return RgbColor.Black;
}
}
#!csharp
class SolidAngle : DirectIllum {
public SolidAngle(int spp) : base(spp) { }
protected override RgbColor EstimateIncidentRadiance(in Ray ray, in SurfacePoint hit, RNG rng) {
// Select a light source
var light = scene.Emitters[rng.NextInt(0, scene.Emitters.Count)];
float lightSelectProb = 1.0f / scene.Emitters.Count;
// Sample a point on the light source
var lightSample = light.SampleSolidAngle(hit, rng.NextFloat2D());
Vector3 lightToSurface = Vector3.Normalize(hit.Position - lightSample.Point.Position);
if (!scene.Raytracer.IsOccluded(hit, lightSample.Point)) {
var emission = light.EmittedRadiance(lightSample.Point, lightToSurface);
float jacobian = SampleWarp.SurfaceAreaToSolidAngle(hit, lightSample.Point);
var bsdfCos = hit.Material.EvaluateWithCosine(hit, -ray.Direction, -lightToSurface, false);
var pdf = lightSample.Pdf * lightSelectProb;
return emission / pdf * jacobian * bsdfCos;
}
return RgbColor.Black;
}
}
#!csharp
scene.FrameBuffer = new(512, 512, "");
new UniformArea(1).Render(scene);
var uniform = scene.FrameBuffer.Image;
scene.FrameBuffer = new(512, 512, "");
new SolidAngle(1).Render(scene);
var solidAngle = scene.FrameBuffer.Image;
Metrics.RelMSE(uniform, reference).Display();
Metrics.RelMSE(solidAngle, reference).Display();
HTML(FlipBook.Make(("uniform", uniform), ("spherical", solidAngle)))