Skip to content

Commit 94b03e6

Browse files
committed
Add basic R-MIS estimator
1 parent 6c03ae9 commit 94b03e6

File tree

9 files changed

+1549
-36
lines changed

9 files changed

+1549
-36
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,4 @@ _deps
7878
### Blobs ###
7979
/build
8080
/out
81-
assignment.html
81+
/renders

framework/third_party/glm/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
cmake_minimum_required(VERSION 3.2 FATAL_ERROR)
2-
cmake_policy(VERSION 3.2)
1+
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2+
cmake_policy(VERSION 3.5)
33

44

55
file(READ "glm/detail/setup.hpp" GLM_SETUP_FILE)

src/main.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ int main(int argc, char** argv) {
9595
break;
9696
}
9797
case GLFW_KEY_M: { // Change render mode and reset temporal predecessor
98-
viewMode = viewMode == ViewMode::Rasterization ? ViewMode::RayTracing : ViewMode::Rasterization;
99-
previousFrameGrid = nullptr;
98+
viewMode = viewMode == ViewMode::Rasterization ? ViewMode::ReSTIR : ViewMode::Rasterization;
99+
previousFrameGrid.reset();
100100
break;
101101
}
102102
};
@@ -160,10 +160,10 @@ int main(int argc, char** argv) {
160160
glPopAttrib();
161161
}
162162
} break;
163-
case ViewMode::RayTracing: {
163+
case ViewMode::ReSTIR: {
164164
const auto start = std::chrono::high_resolution_clock::now();
165165
screen.clear(glm::vec3(0.0f));
166-
previousFrameGrid = make_shared<ReservoirGrid>(renderRayTracing(previousFrameGrid, scene, camera, bvh, screen, camera.getLastDelta(), config.features));
166+
previousFrameGrid = make_shared<ReservoirGrid>(renderReSTIR(previousFrameGrid, scene, camera, bvh, screen, config.features));
167167
screen.setPixel(0, 0, glm::vec3(1.0f));
168168
screen.draw(); // Takes the image generated using ray tracing and outputs it to the screen using OpenGL.
169169
const auto end = std::chrono::high_resolution_clock::now();
@@ -218,7 +218,7 @@ int main(int argc, char** argv) {
218218
screen.clear(glm::vec3(0.0f));
219219
Trackball camera { &window, glm::radians(cameraConfig.fieldOfView), cameraConfig.distanceFromLookAt };
220220
camera.setCamera(cameraConfig.lookAt, glm::radians(cameraConfig.rotation), cameraConfig.distanceFromLookAt);
221-
previousFrameGrid = make_shared<ReservoirGrid>(renderRayTracing(previousFrameGrid, scene, camera, bvh, screen, camera.getLastDelta(), config.features));
221+
previousFrameGrid = make_shared<ReservoirGrid>(renderReSTIR(previousFrameGrid, scene, camera, bvh, screen, config.features));
222222
const auto filename_base = fmt::format("{}_{}_cam_{}", sceneName, start_time_string, index);
223223
const auto filepath = config.outputDir / (filename_base + ".bmp");
224224
fmt::print("Image {} saved to {}\n", index, filepath.string());

src/rendering/render.cpp

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,19 @@ ReservoirGrid genInitialSamples(const Scene& scene, const Trackball& camera, con
3636
return initialSamples;
3737
}
3838

39+
glm::vec3 finalShading(const Reservoir& reservoir, const Ray& primaryRay, const BvhInterface& bvh, const Features& features) {
40+
glm::vec3 finalColor(0.0f);
41+
for (const SampleData& sample : reservoir.outputSamples) {
42+
glm::vec3 sampleColor = testVisibilityLightSample(sample.lightSample.position, bvh, features, primaryRay, reservoir.hitInfo) ?
43+
computeShading(sample.lightSample.position, sample.lightSample.color, features, primaryRay, reservoir.hitInfo) :
44+
glm::vec3(0.0f);
45+
sampleColor *= sample.outputWeight;
46+
finalColor += sampleColor;
47+
}
48+
finalColor /= reservoir.outputSamples.size(); // Divide final shading value by number of samples
49+
return finalColor;
50+
}
51+
3952
void spatialReuse(ReservoirGrid& reservoirGrid, const BvhInterface& bvh, const Screen& screen, const Features& features) {
4053
// Uniform selection of neighbours in N pixel Manhattan distance radius
4154
std::random_device rd;
@@ -86,7 +99,7 @@ void spatialReuse(ReservoirGrid& reservoirGrid, const BvhInterface& bvh, const S
8699
}
87100

88101
void temporalReuse(ReservoirGrid& reservoirGrid, ReservoirGrid& previousFrameGrid, const BvhInterface& bvh,
89-
Screen& screen, const glm::vec2 motionVector, const Features& features) {
102+
Screen& screen, const Features& features) {
90103
glm::ivec2 windowResolution = screen.resolution();
91104
#ifdef NDEBUG
92105
#pragma omp parallel for schedule(guided)
@@ -116,12 +129,12 @@ void temporalReuse(ReservoirGrid& reservoirGrid, ReservoirGrid& previousFrameGri
116129
}
117130
}
118131

119-
ReservoirGrid renderRayTracing(std::shared_ptr<ReservoirGrid> previousFrameGrid,
120-
const Scene& scene, const Trackball& camera,
121-
const BvhInterface& bvh, Screen& screen,
122-
const glm::vec2 motionVector, const Features& features) {
132+
ReservoirGrid renderReSTIR(std::shared_ptr<ReservoirGrid> previousFrameGrid,
133+
const Scene& scene, const Trackball& camera,
134+
const BvhInterface& bvh, Screen& screen,
135+
const Features& features) {
123136
ReservoirGrid reservoirGrid = genInitialSamples(scene, camera, bvh, screen, features);
124-
if (features.temporalReuse && previousFrameGrid) { temporalReuse(reservoirGrid, *previousFrameGrid.get(), bvh, screen, motionVector, features); }
137+
if (features.temporalReuse && previousFrameGrid) { temporalReuse(reservoirGrid, *previousFrameGrid.get(), bvh, screen, features); }
125138
if (features.spatialReuse) { spatialReuse(reservoirGrid, bvh, screen, features); }
126139

127140
// Final shading
@@ -132,16 +145,8 @@ ReservoirGrid renderRayTracing(std::shared_ptr<ReservoirGrid> previousFrameGrid,
132145
for (int y = 0; y < windowResolution.y; y++) {
133146
for (int x = 0; x != windowResolution.x; x++) {
134147
// Compute shading from final sample(s)
135-
glm::vec3 finalColor(0.0f);
136-
const Reservoir& reservoir = reservoirGrid[y][x];
137-
for (const SampleData& sample : reservoir.outputSamples) {
138-
glm::vec3 sampleColor = testVisibilityLightSample(sample.lightSample.position, bvh, features, reservoir.cameraRay, reservoir.hitInfo) ?
139-
computeShading(sample.lightSample.position, sample.lightSample.color, features, reservoir.cameraRay, reservoir.hitInfo) :
140-
glm::vec3(0.0f);
141-
sampleColor *= sample.outputWeight;
142-
finalColor += sampleColor;
143-
}
144-
finalColor /= reservoir.outputSamples.size(); // Divide final shading value by number of samples
148+
const Reservoir& reservoir = reservoirGrid[y][x];
149+
glm::vec3 finalColor = finalShading(reservoir, reservoir.cameraRay, bvh, features);
145150

146151
// Apply tone mapping and set final pixel color
147152
if (features.enableToneMapping) { finalColor = exposureToneMapping(finalColor, features); }
@@ -151,4 +156,33 @@ ReservoirGrid renderRayTracing(std::shared_ptr<ReservoirGrid> previousFrameGrid,
151156

152157
// Return current frame's final grid for temporal reuse
153158
return reservoirGrid;
154-
}
159+
}
160+
161+
void renderRMIS(const Scene& scene, const Trackball& camera, const BvhInterface& bvh, Screen& screen, const Features& features) {
162+
ReservoirGrid reservoirGrid = genInitialSamples(scene, camera, bvh, screen, features);
163+
glm::ivec2 windowResolution = screen.resolution();
164+
165+
#ifdef NDEBUG
166+
#pragma omp parallel for schedule(guided)
167+
#endif
168+
for (int y = 0; y < windowResolution.y; y++) {
169+
for (int x = 0; x != windowResolution.x; x++) {
170+
const Ray& primaryRay = reservoirGrid[y][x].cameraRay;
171+
172+
// Combine samples from all pixels in 3x3 neighborhood
173+
glm::vec3 finalColor(0.0f);
174+
for (int sampleY = y - 1; sampleY <= y + 1; sampleY++) {
175+
for (int sampleX = x - 1; sampleX <= x + 1; sampleX++) {
176+
int neighbourY = std::clamp(sampleY, 0, windowResolution.y - 1);
177+
int neighbourX = std::clamp(sampleX, 0, windowResolution.x - 1);
178+
finalColor += finalShading(reservoirGrid[neighbourY][neighbourX], primaryRay, bvh, features);
179+
}
180+
}
181+
finalColor *= (1.0f / 9.0f); // TODO: Change to actual OMIS MIS weights
182+
183+
// Apply tone mapping and set final pixel color
184+
if (features.enableToneMapping) { finalColor = exposureToneMapping(finalColor, features); }
185+
screen.setPixel(x, y, finalColor);
186+
}
187+
}
188+
}

src/rendering/render.h

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,20 @@ class Trackball;
1616
class BvhInterface;
1717
struct Features;
1818

19+
// Common
1920
ReservoirGrid genInitialSamples(const Scene& scene, const Trackball& camera, const BvhInterface& bvh, const Screen& screen, const Features& features);
21+
glm::vec3 finalShading(const Reservoir& reservoir, const Ray& primaryRay, const BvhInterface& bvh, const Features& features);
2022

23+
// ReSTIR-specific
2124
void spatialReuse(ReservoirGrid& reservoirGrid, const BvhInterface& bvh, const Screen& screen, const Features& features);
22-
2325
void temporalReuse(ReservoirGrid& reservoirGrid, ReservoirGrid& previousFrameGrid, const BvhInterface& bvh,
24-
Screen& screen, const glm::vec2 motionVector, const Features& features);
26+
Screen& screen, const Features& features);
27+
28+
// Render using ReSTIR
29+
ReservoirGrid renderReSTIR(std::shared_ptr<ReservoirGrid> previousFrameGrid,
30+
const Scene& scene, const Trackball& camera,
31+
const BvhInterface& bvh, Screen& screen,
32+
const Features& features);
2533

26-
// Main rendering function.
27-
ReservoirGrid renderRayTracing(std::shared_ptr<ReservoirGrid> previousFrameGrid,
28-
const Scene& scene, const Trackball& camera,
29-
const BvhInterface& bvh, Screen& screen,
30-
const glm::vec2 motionVector, const Features& features);
34+
// Render using R-MIS
35+
void renderRMIS(const Scene& scene, const Trackball& camera, const BvhInterface& bvh, Screen& screen, const Features& features);

src/scene/light.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ Reservoir genCanonicalSamples(const Scene& scene, const BvhInterface& bvh, const
5151
}
5252

5353
// Uniform selection of light sources
54-
// TODO: Figure out better solution than uniform sampling (fuck you, point lights)
5554
std::random_device rd;
5655
std::mt19937 gen(rd());
5756
std::uniform_int_distribution<> distr(0, scene.lights.size() - 1UL);

src/ui/ui.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void UiManager::drawSceneSelection() {
117117
}
118118

119119
void UiManager::drawViewModeSelection() {
120-
constexpr std::array items { "Rasterization", "Ray Traced" };
120+
constexpr std::array items { "Rasterization", "ReSTIR", "OMIS" };
121121
ImGui::Combo("View mode", reinterpret_cast<int*>(&viewMode), items.data(), int(items.size()));
122122
}
123123

@@ -173,7 +173,7 @@ void UiManager::drawRenderToFile() {
173173
// Perform a new render and measure the time it took to generate the image.
174174
using clock = std::chrono::high_resolution_clock;
175175
const auto start = clock::now();
176-
previousFrameGrid = std::make_shared<ReservoirGrid>(renderRayTracing(previousFrameGrid, scene, camera, bvh, screen, camera.getLastDelta(), config.features));
176+
renderRMIS(scene, camera, bvh, screen, config.features);
177177
const auto end = clock::now();
178178
std::cout << "Time to render image: " << std::chrono::duration<float, std::milli>(end - start).count() << " milliseconds" << std::endl;
179179

src/utils/common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ enum class DrawMode {
1313

1414
enum class ViewMode {
1515
Rasterization = 0,
16-
RayTracing = 1
16+
ReSTIR,
17+
OMIS
1718
};
1819

1920
struct HitInfo {

0 commit comments

Comments
 (0)