Skip to content

Commit 77e70ce

Browse files
Russian Roulette, Conditional Compilation
1 parent bf09f0b commit 77e70ce

13 files changed

+140
-28
lines changed

src/Main.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,22 @@ void MainLoop(void* arg)
283283

284284
if (ImGui::CollapsingHeader("Render Settings"))
285285
{
286+
bool requiresReload = false;
287+
Vec3* bgCol = &renderOptions.bgColor;
288+
286289
optionsChanged |= ImGui::SliderInt("Max Depth", &renderOptions.maxDepth, 1, 10);
287-
optionsChanged |= ImGui::Checkbox("Use envmap", &renderOptions.useEnvMap);
290+
requiresReload |= ImGui::Checkbox("Enable HDR", &renderOptions.useEnvMap);
288291
optionsChanged |= ImGui::SliderFloat("HDR multiplier", &renderOptions.hdrMultiplier, 0.1f, 10.0f);
292+
requiresReload |= ImGui::Checkbox("Enable RR", &renderOptions.enableRR);
293+
requiresReload |= ImGui::SliderInt("RR Depth", &renderOptions.RRDepth, 1, 10);
294+
requiresReload |= ImGui::Checkbox("Enable Constant BG", &renderOptions.useConstantBg);
295+
optionsChanged |= ImGui::ColorEdit3("Background Color", (float*)bgCol, 0);
296+
297+
if (requiresReload)
298+
{
299+
scene->renderOptions = renderOptions;
300+
InitRenderer();
301+
}
289302
}
290303

291304
if (ImGui::CollapsingHeader("Camera"))

src/core/Program.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace GLSLPT
5656
glDeleteProgram(object);
5757
object = 0;
5858
printf("Error %s\n", msg.c_str());
59-
throw std::runtime_error(msg);
59+
throw std::runtime_error(msg.c_str());
6060
}
6161
}
6262

src/core/Renderer.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,16 @@
2929

3030
#include "Config.h"
3131
#include "Renderer.h"
32+
#include "ShaderIncludes.h"
3233
#include "Scene.h"
3334

3435
namespace GLSLPT
3536
{
36-
Program *LoadShaders(const std::string& vertShaderFilename, const std::string& fragShaderFilename)
37+
Program *LoadShaders(const ShaderInclude::ShaderSource& vertShaderObj, const ShaderInclude::ShaderSource& fragShaderObj)
3738
{
3839
std::vector<Shader> shaders;
39-
shaders.push_back(Shader(vertShaderFilename, GL_VERTEX_SHADER));
40-
shaders.push_back(Shader(fragShaderFilename, GL_FRAGMENT_SHADER));
40+
shaders.push_back(Shader(vertShaderObj, GL_VERTEX_SHADER));
41+
shaders.push_back(Shader(fragShaderObj, GL_FRAGMENT_SHADER));
4142
return new Program(shaders);
4243
}
4344

src/core/Renderer.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,13 @@
3232
#include "Quad.h"
3333
#include "Program.h"
3434
#include <Vec2.h>
35+
#include <Vec3.h>
3536

3637
#include <vector>
3738

3839
namespace GLSLPT
3940
{
40-
Program *LoadShaders(const std::string &vertShaderFilename, const std::string &fragShaderFilename);
41+
Program* LoadShaders(const ShaderInclude::ShaderSource& vertShaderObj, const ShaderInclude::ShaderSource& fragShaderObj);
4142

4243
struct RenderOptions
4344
{
@@ -49,13 +50,21 @@ namespace GLSLPT
4950
useEnvMap = false;
5051
resolution = iVec2(1280, 720);
5152
hdrMultiplier = 1.0f;
53+
enableRR = true;
54+
useConstantBg = false;
55+
RRDepth = 2;
56+
bgColor = Vec3(1.0f, 1.0f, 1.0f);
5257
}
5358
iVec2 resolution;
5459
int maxDepth;
5560
int tileWidth;
5661
int tileHeight;
5762
bool useEnvMap;
63+
bool enableRR;
64+
bool useConstantBg;
65+
int RRDepth;
5866
float hdrMultiplier;
67+
Vec3 bgColor;
5968
};
6069

6170
class Scene;

src/core/Shader.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,17 @@
2828
*/
2929

3030
#include "Shader.h"
31-
#include "ShaderIncludes.h"
3231
#include <iostream>
3332
#include <fstream>
3433
#include <sstream>
3534

3635
namespace GLSLPT
3736
{
38-
Shader::Shader(const std::string& filePath, GLenum shaderType)
37+
Shader::Shader(const ShaderInclude::ShaderSource& sourceObj, GLenum shaderType)
3938
{
40-
std::string source = GLSLPT::ShaderInclude::load(filePath);
41-
4239
object = glCreateShader(shaderType);
43-
printf("Compiling Shader %s -> %d\n", filePath.c_str(), int(object));
44-
const GLchar *src = (const GLchar *)source.c_str();
40+
printf("Compiling Shader %s -> %d\n", sourceObj.path.c_str(), int(object));
41+
const GLchar *src = (const GLchar *)sourceObj.src.c_str();
4542
glShaderSource(object, 1, &src, 0);
4643
glCompileShader(object);
4744
GLint success = 0;
@@ -53,7 +50,7 @@ namespace GLSLPT
5350
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &logSize);
5451
char *info = new char[logSize + 1];
5552
glGetShaderInfoLog(object, logSize, NULL, info);
56-
msg += filePath;
53+
msg += sourceObj.path;
5754
msg += "\n";
5855
msg += info;
5956
delete[] info;

src/core/Shader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#pragma once
3131

3232
#include <string>
33+
#include "ShaderIncludes.h"
3334
#include "Config.h"
3435

3536
namespace GLSLPT
@@ -39,7 +40,7 @@ namespace GLSLPT
3940
private:
4041
GLuint object;
4142
public:
42-
Shader(const std::string& filePath, GLuint shaderType);
43+
Shader(const ShaderInclude::ShaderSource& sourceObj, GLuint shaderType);
4344
GLuint getObject() const;
4445
};
4546
}

src/core/ShaderIncludes.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,15 @@ namespace GLSLPT
6767
class ShaderInclude
6868
{
6969
public:
70+
71+
struct ShaderSource
72+
{
73+
std::string src;
74+
std::string path;
75+
};
76+
7077
// Return the source code of the complete shader
71-
static std::string load(std::string path, std::string includeIndentifier = "#include")
78+
static ShaderSource load(std::string path, std::string includeIndentifier = "#include")
7279
{
7380
includeIndentifier += ' ';
7481
static bool isRecursiveCall = false;
@@ -79,7 +86,7 @@ namespace GLSLPT
7986
if (!file.is_open())
8087
{
8188
std::cerr << "ERROR: could not open the shader at: " << path << "\n" << std::endl;
82-
return fullSourceCode;
89+
return ShaderSource{ fullSourceCode, path };
8390
}
8491

8592
std::string lineBuffer;
@@ -99,7 +106,7 @@ namespace GLSLPT
99106
// By using recursion, the new include file can be extracted
100107
// and inserted at this location in the shader source code
101108
isRecursiveCall = true;
102-
fullSourceCode += load(lineBuffer);
109+
fullSourceCode += load(lineBuffer).src;
103110

104111
// Do not add this line to the shader source code, as the include
105112
// path would generate a compilation issue in the final source code
@@ -116,9 +123,11 @@ namespace GLSLPT
116123

117124
file.close();
118125

119-
return fullSourceCode;
126+
return ShaderSource{ fullSourceCode, path };;
120127
}
121128

129+
130+
122131
private:
123132
static void getFilePath(const std::string& fullPath, std::string& pathWithoutFileName)
124133
{

src/core/TiledRenderer.cpp

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,49 @@ namespace GLSLPT
8787
// Shaders
8888
//----------------------------------------------------------
8989

90-
pathTraceShader = LoadShaders(shadersDirectory + "common/vertex.glsl", shadersDirectory + "tiled.glsl");
91-
pathTraceShaderLowRes = LoadShaders(shadersDirectory + "common/vertex.glsl", shadersDirectory + "progressive.glsl");
92-
accumShader = LoadShaders(shadersDirectory + "common/vertex.glsl", shadersDirectory + "accumulation.glsl");
93-
tileOutputShader = LoadShaders(shadersDirectory + "common/vertex.glsl", shadersDirectory + "tileOutput.glsl");
94-
outputShader = LoadShaders(shadersDirectory + "common/vertex.glsl", shadersDirectory + "output.glsl");
90+
ShaderInclude::ShaderSource vertexShaderSrcObj = ShaderInclude::load(shadersDirectory + "common/vertex.glsl");
91+
ShaderInclude::ShaderSource pathTraceShaderSrcObj = ShaderInclude::load(shadersDirectory + "tiled.glsl");
92+
ShaderInclude::ShaderSource pathTraceShaderLowResSrcObj = ShaderInclude::load(shadersDirectory + "progressive.glsl");
93+
ShaderInclude::ShaderSource accumShaderSrcObj = ShaderInclude::load(shadersDirectory + "accumulation.glsl");
94+
ShaderInclude::ShaderSource tileOutputShaderSrcObj = ShaderInclude::load(shadersDirectory + "tileOutput.glsl");
95+
ShaderInclude::ShaderSource outputShaderSrcObj = ShaderInclude::load(shadersDirectory + "output.glsl");
96+
97+
// Add preprocessor defines for conditional compilation
98+
std::string defines = "";
99+
if (scene->renderOptions.useEnvMap && scene->hdrData != nullptr)
100+
defines += "#define ENVMAP\n";
101+
if (!scene->lights.empty())
102+
defines += "#define LIGHTS\n";
103+
if (scene->renderOptions.enableRR)
104+
{
105+
defines += "#define RR\n";
106+
defines += "#define RR_DEPTH " + std::to_string(scene->renderOptions.RRDepth) + "\n";
107+
}
108+
if (scene->renderOptions.useConstantBg)
109+
defines += "#define CONSTANT_BG\n";
110+
111+
if (defines.size() > 0)
112+
{
113+
size_t idx = pathTraceShaderSrcObj.src.find("#version");
114+
if (idx != -1)
115+
idx = pathTraceShaderSrcObj.src.find("\n", idx);
116+
else
117+
idx = 0;
118+
pathTraceShaderSrcObj.src.insert(idx + 1, defines);
119+
120+
idx = pathTraceShaderLowResSrcObj.src.find("#version");
121+
if (idx != -1)
122+
idx = pathTraceShaderLowResSrcObj.src.find("\n", idx);
123+
else
124+
idx = 0;
125+
pathTraceShaderLowResSrcObj.src.insert(idx + 1, defines);
126+
}
127+
128+
pathTraceShader = LoadShaders(vertexShaderSrcObj, pathTraceShaderSrcObj);
129+
pathTraceShaderLowRes = LoadShaders(vertexShaderSrcObj, pathTraceShaderLowResSrcObj);
130+
accumShader = LoadShaders(vertexShaderSrcObj, accumShaderSrcObj);
131+
tileOutputShader = LoadShaders(vertexShaderSrcObj, tileOutputShaderSrcObj);
132+
outputShader = LoadShaders(vertexShaderSrcObj, outputShaderSrcObj);
95133

96134
printf("Debug sizes : %d %d - %d %d\n", tileWidth, tileHeight, screenSize.x, screenSize.y);
97135
//----------------------------------------------------------
@@ -414,6 +452,7 @@ namespace GLSLPT
414452
glUniform1i(glGetUniformLocation(shaderObject, "maxDepth"), scene->renderOptions.maxDepth);
415453
glUniform1i(glGetUniformLocation(shaderObject, "tileX"), tileX);
416454
glUniform1i(glGetUniformLocation(shaderObject, "tileY"), tileY);
455+
glUniform3f(glGetUniformLocation(shaderObject, "bgColor"), scene->renderOptions.bgColor.x, scene->renderOptions.bgColor.y, scene->renderOptions.bgColor.z);
417456
pathTraceShader->StopUsing();
418457

419458
pathTraceShaderLowRes->Use();
@@ -428,6 +467,8 @@ namespace GLSLPT
428467
glUniform1i(glGetUniformLocation(shaderObject, "useEnvMap"), scene->hdrData == nullptr ? false : scene->renderOptions.useEnvMap);
429468
glUniform1f(glGetUniformLocation(shaderObject, "hdrMultiplier"), scene->renderOptions.hdrMultiplier);
430469
glUniform1i(glGetUniformLocation(shaderObject, "maxDepth"), scene->camera->isMoving || scene->instancesModified ? 2: scene->renderOptions.maxDepth);
470+
glUniform3f(glGetUniformLocation(shaderObject, "camera.position"), scene->camera->position.x, scene->camera->position.y, scene->camera->position.z);
471+
glUniform3f(glGetUniformLocation(shaderObject, "bgColor"), scene->renderOptions.bgColor.x, scene->renderOptions.bgColor.y, scene->renderOptions.bgColor.z);
431472
pathTraceShaderLowRes->StopUsing();
432473

433474
outputShader->Use();

src/loaders/Loader.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ namespace GLSLPT
213213
if (strstr(line, "Renderer"))
214214
{
215215
char envMap[200] = "None";
216+
char enableRR[10] = "None";
216217

217218
while (fgets(line, kMaxLineLength, file))
218219
{
@@ -226,13 +227,20 @@ namespace GLSLPT
226227
sscanf(line, " maxDepth %i", &renderOptions.maxDepth);
227228
sscanf(line, " tileWidth %i", &renderOptions.tileWidth);
228229
sscanf(line, " tileHeight %i", &renderOptions.tileHeight);
230+
sscanf(line, " enableRR %s", enableRR);
231+
sscanf(line, " RRDepth %i", &renderOptions.RRDepth);
229232
}
230233

231234
if (strcmp(envMap, "None") != 0)
232235
{
233236
scene->AddHDR(path + envMap);
234237
renderOptions.useEnvMap = true;
235238
}
239+
240+
if (strcmp(enableRR, "False") == 0)
241+
renderOptions.enableRR = false;
242+
else if (strcmp(enableRR, "True") == 0)
243+
renderOptions.enableRR = true;
236244
}
237245

238246

src/shaders/common/closest_hit.glsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ float ClosestHit(Ray r, inout State state, inout LightSampleRec lightSampleRec)
3434
float t = INFINITY;
3535
float d;
3636

37+
#ifdef LIGHTS
3738
// Intersect Emitters
3839
for (int i = 0; i < numOfLights; i++)
3940
{
@@ -81,6 +82,7 @@ float ClosestHit(Ray r, inout State state, inout LightSampleRec lightSampleRec)
8182
}
8283
}
8384
}
85+
#endif
8486

8587
int stack[64];
8688
int ptr = 0;

src/shaders/common/pathtrace.glsl

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ vec3 DirectLight(in Ray r, in State state)
142142
vec3 surfacePos = state.fhp + state.ffnormal * EPS;
143143

144144
// Environment Light
145-
if (useEnvMap)
145+
#ifdef ENVMAP
146+
#ifndef CONSTANT_BG
146147
{
147148
vec3 color;
148149
vec4 dirPdf = EnvSample(color);
@@ -165,9 +166,11 @@ vec3 DirectLight(in Ray r, in State state)
165166
}
166167
}
167168
}
169+
#endif
170+
#endif
168171

169172
// Analytic Lights
170-
if (numOfLights > 0)
173+
#ifdef LIGHTS
171174
{
172175
LightSampleRec lightSampleRec;
173176
Light light;
@@ -204,8 +207,8 @@ vec3 DirectLight(in Ray r, in State state)
204207

205208
L += powerHeuristic(lightPdf, bsdfPdf) * f * abs(dot(state.ffnormal, lightDir)) * lightSampleRec.emission / lightPdf;
206209
}
207-
208210
}
211+
#endif
209212

210213
return L;
211214
}
@@ -228,7 +231,10 @@ vec3 PathTrace(Ray r)
228231

229232
if (t == INFINITY)
230233
{
231-
if (useEnvMap)
234+
#ifdef CONSTANT_BG
235+
radiance += bgColor * throughput;
236+
#else
237+
#ifdef ENVMAP
232238
{
233239
float misWeight = 1.0f;
234240
vec2 uv = vec2((PI + atan(r.direction.z, r.direction.x)) * (1.0 / TWO_PI), acos(r.direction.y) * (1.0 / PI));
@@ -240,6 +246,8 @@ vec3 PathTrace(Ray r)
240246
}
241247
radiance += misWeight * texture(hdrTex, uv).xyz * throughput * hdrMultiplier;
242248
}
249+
#endif
250+
#endif
243251
return radiance;
244252
}
245253

@@ -248,12 +256,13 @@ vec3 PathTrace(Ray r)
248256

249257
radiance += state.mat.emission * throughput;
250258

259+
#ifdef LIGHTS
251260
if (state.isEmitter)
252261
{
253262
radiance += EmitterSample(r, state, lightSampleRec, bsdfSampleRec) * throughput;
254263
break;
255264
}
256-
265+
#endif
257266
radiance += DirectLight(r, state) * throughput;
258267

259268
bsdfSampleRec.bsdfDir = DisneySample(r, state);
@@ -263,6 +272,21 @@ vec3 PathTrace(Ray r)
263272
throughput *= DisneyEval(r, state, bsdfSampleRec.bsdfDir) * abs(dot(state.ffnormal, bsdfSampleRec.bsdfDir)) / bsdfSampleRec.pdf;
264273
else
265274
break;
275+
276+
#ifdef RR
277+
// Russian roulette
278+
if (depth >= RR_DEPTH)
279+
{
280+
float q = max(max(throughput.x, max(throughput.y, throughput.z)), 0.001);
281+
if (rand() > q)
282+
break;
283+
284+
throughput *= 1.0 / q;
285+
}
286+
#endif
287+
288+
289+
266290

267291
r.direction = bsdfSampleRec.bsdfDir;
268292
r.origin = state.fhp + r.direction * EPS;

0 commit comments

Comments
 (0)