Skip to content

Commit 9a47337

Browse files
Distant/Directional Light
1 parent 272915a commit 9a47337

File tree

5 files changed

+82
-51
lines changed

5 files changed

+82
-51
lines changed

src/core/Scene.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ namespace GLSLPT
4343
enum LightType
4444
{
4545
RectLight,
46-
SphereLight
46+
SphereLight,
47+
DistantLight
4748
};
4849

4950
struct Light

src/loaders/Loader.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ namespace GLSLPT
174174
light.type = LightType::SphereLight;
175175
light.area = 4.0f * PI * light.radius * light.radius;
176176
}
177+
else if (strcmp(light_type, "Distant") == 0)
178+
{
179+
light.type = LightType::DistantLight;
180+
light.area = 0.0f;
181+
}
177182

178183
scene->AddLight(light);
179184
}

src/shaders/common/globals.glsl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@
2727
#define INFINITY 1000000.0
2828
#define EPS 0.0001
2929

30-
#define REFL 0
31-
#define REFR 1
32-
#define SUBS 2
33-
3430
#define QUAD_LIGHT 0
3531
#define SPHERE_LIGHT 1
32+
#define DISTANT_LIGHT 2
3633

3734
mat4 transform;
3835

@@ -122,9 +119,10 @@ struct BsdfSampleRec
122119

123120
struct LightSampleRec
124121
{
125-
vec3 surfacePos;
126122
vec3 normal;
127123
vec3 emission;
124+
vec3 direction;
125+
float dist;
128126
float pdf;
129127
};
130128

src/shaders/common/pathtrace.glsl

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,23 @@ void GetNormalsAndTexCoord(inout State state, inout Ray r)
5252
state.normal = normal;
5353
state.ffnormal = dot(normal, r.direction) <= 0.0 ? normal : normal * -1.0;
5454

55-
Onb(state.ffnormal, state.tangent, state.bitangent);
55+
Onb(state.normal, state.tangent, state.bitangent);
5656
}
5757

5858
//-----------------------------------------------------------------------
5959
void GetMaterialsAndTextures(inout State state, in Ray r)
6060
//-----------------------------------------------------------------------
6161
{
62-
int index = state.matID;
62+
int index = state.matID * 7;
6363
Material mat;
6464

65-
vec4 param1 = texelFetch(materialsTex, ivec2(index * 7 + 0, 0), 0);
66-
vec4 param2 = texelFetch(materialsTex, ivec2(index * 7 + 1, 0), 0);
67-
vec4 param3 = texelFetch(materialsTex, ivec2(index * 7 + 2, 0), 0);
68-
vec4 param4 = texelFetch(materialsTex, ivec2(index * 7 + 3, 0), 0);
69-
vec4 param5 = texelFetch(materialsTex, ivec2(index * 7 + 4, 0), 0);
70-
vec4 param6 = texelFetch(materialsTex, ivec2(index * 7 + 5, 0), 0);
71-
vec4 param7 = texelFetch(materialsTex, ivec2(index * 7 + 6, 0), 0);
65+
vec4 param1 = texelFetch(materialsTex, ivec2(index + 0, 0), 0);
66+
vec4 param2 = texelFetch(materialsTex, ivec2(index + 1, 0), 0);
67+
vec4 param3 = texelFetch(materialsTex, ivec2(index + 2, 0), 0);
68+
vec4 param4 = texelFetch(materialsTex, ivec2(index + 3, 0), 0);
69+
vec4 param5 = texelFetch(materialsTex, ivec2(index + 4, 0), 0);
70+
vec4 param6 = texelFetch(materialsTex, ivec2(index + 5, 0), 0);
71+
vec4 param7 = texelFetch(materialsTex, ivec2(index + 6, 0), 0);
7272

7373
mat.albedo = param1.xyz;
7474
mat.specular = param1.w;
@@ -106,9 +106,10 @@ void GetMaterialsAndTextures(inout State state, in Ray r)
106106
if (int(mat.texIDs.y) >= 0)
107107
{
108108
vec2 matRgh;
109+
// TODO: Change metallic roughness maps in repo to linear space and remove gamma correction
109110
matRgh = pow(texture(textureMapsArrayTex, vec3(texUV, int(mat.texIDs.y))).zy, vec2(2.2));
110111
mat.metallic = matRgh.x;
111-
mat.roughness = matRgh.y;
112+
mat.roughness = max(matRgh.y, 0.001);
112113
}
113114

114115
// Normal Map
@@ -117,21 +118,21 @@ void GetMaterialsAndTextures(inout State state, in Ray r)
117118
vec3 nrm = texture(textureMapsArrayTex, vec3(texUV, int(mat.texIDs.z))).xyz;
118119
nrm = normalize(nrm * 2.0 - 1.0);
119120

120-
// Orthonormal Basis
121121
vec3 T, B;
122-
Onb(state.ffnormal, T, B);
122+
Onb(state.normal, T, B);
123123

124-
nrm = T * nrm.x + B * nrm.y + state.ffnormal * nrm.z;
124+
nrm = T * nrm.x + B * nrm.y + state.normal * nrm.z;
125125
state.normal = normalize(nrm);
126126
state.ffnormal = dot(state.normal, r.direction) <= 0.0 ? state.normal : state.normal * -1.0;
127127

128-
Onb(state.ffnormal, state.tangent, state.bitangent);
128+
Onb(state.normal, state.tangent, state.bitangent);
129129
}
130130

131+
// Commented out the following as anisotropic param is temporarily unused.
131132
// Calculate anisotropic roughness along the tangent and bitangent directions
132-
float aspect = sqrt(1.0 - mat.anisotropic * 0.9);
133-
mat.ax = max(0.001, mat.roughness / aspect);
134-
mat.ay = max(0.001, mat.roughness * aspect);
133+
// float aspect = sqrt(1.0 - mat.anisotropic * 0.9);
134+
// mat.ax = max(0.001, mat.roughness / aspect);
135+
// mat.ay = max(0.001, mat.roughness * aspect);
135136

136137
state.mat = mat;
137138
state.eta = dot(state.normal, state.ffnormal) > 0.0 ? (1.0 / mat.ior) : mat.ior;
@@ -180,38 +181,36 @@ vec3 DirectLight(in Ray r, in State state)
180181
Light light;
181182

182183
//Pick a light to sample
183-
int index = int(rand() * float(numOfLights));
184+
int index = int(rand() * float(numOfLights)) * 5;
184185

185186
// Fetch light Data
186-
vec3 position = texelFetch(lightsTex, ivec2(index * 5 + 0, 0), 0).xyz;
187-
vec3 emission = texelFetch(lightsTex, ivec2(index * 5 + 1, 0), 0).xyz;
188-
vec3 u = texelFetch(lightsTex, ivec2(index * 5 + 2, 0), 0).xyz; // u vector for rect
189-
vec3 v = texelFetch(lightsTex, ivec2(index * 5 + 3, 0), 0).xyz; // v vector for rect
190-
vec3 params = texelFetch(lightsTex, ivec2(index * 5 + 4, 0), 0).xyz;
187+
vec3 position = texelFetch(lightsTex, ivec2(index + 0, 0), 0).xyz;
188+
vec3 emission = texelFetch(lightsTex, ivec2(index + 1, 0), 0).xyz;
189+
vec3 u = texelFetch(lightsTex, ivec2(index + 2, 0), 0).xyz; // u vector for rect
190+
vec3 v = texelFetch(lightsTex, ivec2(index + 3, 0), 0).xyz; // v vector for rect
191+
vec3 params = texelFetch(lightsTex, ivec2(index + 4, 0), 0).xyz;
191192
float radius = params.x;
192193
float area = params.y;
193-
float type = params.z; // 0->rect, 1->sphere
194+
float type = params.z; // 0->Rect, 1->Sphere, 2->Distant
194195

195196
light = Light(position, emission, u, v, radius, area, type);
196-
sampleLight(light, lightSampleRec);
197+
sampleOneLight(light, surfacePos, lightSampleRec);
197198

198-
vec3 lightDir = lightSampleRec.surfacePos - surfacePos;
199-
float lightDist = length(lightDir);
200-
float lightDistSq = lightDist * lightDist;
201-
lightDir /= lightDist;
202-
203-
if (dot(lightDir, lightSampleRec.normal) < 0.0)
199+
if (dot(lightSampleRec.direction, lightSampleRec.normal) < 0.0)
204200
{
205-
Ray shadowRay = Ray(surfacePos, lightDir);
206-
bool inShadow = AnyHit(shadowRay, lightDist - EPS);
201+
Ray shadowRay = Ray(surfacePos, lightSampleRec.direction);
202+
bool inShadow = AnyHit(shadowRay, lightSampleRec.dist - EPS);
207203

208204
if (!inShadow)
209205
{
210-
bsdfSampleRec.f = DisneyEval(state, -r.direction, state.ffnormal, lightDir, bsdfSampleRec.pdf);
211-
float lightPdf = lightDistSq / (light.area * abs(dot(lightSampleRec.normal, lightDir)));
206+
bsdfSampleRec.f = DisneyEval(state, -r.direction, state.ffnormal, lightSampleRec.direction, bsdfSampleRec.pdf);
207+
208+
float weight = 1.0;
209+
if(light.area > 0.0)
210+
weight = powerHeuristic(lightSampleRec.pdf, bsdfSampleRec.pdf);
212211

213212
if (bsdfSampleRec.pdf > 0.0)
214-
Li += powerHeuristic(lightPdf, bsdfSampleRec.pdf) * bsdfSampleRec.f * abs(dot(state.ffnormal, lightDir)) * lightSampleRec.emission / lightPdf;
213+
Li += weight * bsdfSampleRec.f * abs(dot(state.ffnormal, lightSampleRec.direction)) * lightSampleRec.emission / lightSampleRec.pdf;
215214
}
216215
}
217216
}

src/shaders/common/sampling.glsl

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -188,37 +188,65 @@ float powerHeuristic(float a, float b)
188188
}
189189

190190
//-----------------------------------------------------------------------
191-
void sampleSphereLight(in Light light, inout LightSampleRec lightSampleRec)
191+
void sampleSphereLight(in Light light, in vec3 surfacePos, inout LightSampleRec lightSampleRec)
192192
//-----------------------------------------------------------------------
193193
{
194+
//TODO: Pick a point only on the visible surface of the sphere
195+
194196
float r1 = rand();
195197
float r2 = rand();
196198

197-
lightSampleRec.surfacePos = light.position + UniformSampleSphere(r1, r2) * light.radius;
198-
lightSampleRec.normal = normalize(lightSampleRec.surfacePos - light.position);
199+
vec3 lightSurfacePos = light.position + UniformSampleSphere(r1, r2) * light.radius;
200+
lightSampleRec.direction = lightSurfacePos - surfacePos;
201+
lightSampleRec.dist = length(lightSampleRec.direction);
202+
float distSq = lightSampleRec.dist * lightSampleRec.dist;
203+
lightSampleRec.direction /= lightSampleRec.dist;
204+
lightSampleRec.direction / lightSampleRec.direction;
205+
lightSampleRec.normal = normalize(lightSurfacePos - light.position);
199206
lightSampleRec.emission = light.emission * float(numOfLights);
207+
lightSampleRec.pdf = distSq / (light.area * abs(dot(lightSampleRec.normal, lightSampleRec.direction)));
200208
}
201209

202210
//-----------------------------------------------------------------------
203-
void sampleRectLight(in Light light, inout LightSampleRec lightSampleRec)
211+
void sampleRectLight(in Light light, in vec3 surfacePos, inout LightSampleRec lightSampleRec)
204212
//-----------------------------------------------------------------------
205213
{
206214
float r1 = rand();
207215
float r2 = rand();
208216

209-
lightSampleRec.surfacePos = light.position + light.u * r1 + light.v * r2;
217+
vec3 lightSurfacePos = light.position + light.u * r1 + light.v * r2;
218+
lightSampleRec.direction = lightSurfacePos - surfacePos;
219+
lightSampleRec.dist = length(lightSampleRec.direction);
220+
float distSq = lightSampleRec.dist * lightSampleRec.dist;
221+
lightSampleRec.direction /= lightSampleRec.dist;
210222
lightSampleRec.normal = normalize(cross(light.u, light.v));
211223
lightSampleRec.emission = light.emission * float(numOfLights);
224+
lightSampleRec.pdf = distSq / (light.area * abs(dot(lightSampleRec.normal, lightSampleRec.direction)));
225+
}
226+
227+
//-----------------------------------------------------------------------
228+
void sampleDistantLight(in Light light, in vec3 surfacePos, inout LightSampleRec lightSampleRec)
229+
//-----------------------------------------------------------------------
230+
{
231+
lightSampleRec.direction = normalize(light.position - vec3(0.0));
232+
lightSampleRec.normal = normalize(surfacePos - light.position);
233+
lightSampleRec.emission = light.emission * float(numOfLights);
234+
lightSampleRec.dist = INFINITY;
235+
lightSampleRec.pdf = 1.0;
212236
}
213237

214238
//-----------------------------------------------------------------------
215-
void sampleLight(in Light light, inout LightSampleRec lightSampleRec)
239+
void sampleOneLight(in Light light, in vec3 surfacePos, inout LightSampleRec lightSampleRec)
216240
//-----------------------------------------------------------------------
217241
{
218-
if (int(light.type) == QUAD_LIGHT)
219-
sampleRectLight(light, lightSampleRec);
242+
int type = int(light.type);
243+
244+
if (type == QUAD_LIGHT)
245+
sampleRectLight(light, surfacePos, lightSampleRec);
246+
else if (type == SPHERE_LIGHT)
247+
sampleSphereLight(light, surfacePos, lightSampleRec);
220248
else
221-
sampleSphereLight(light, lightSampleRec);
249+
sampleDistantLight(light, surfacePos, lightSampleRec);
222250
}
223251

224252
#ifdef ENVMAP

0 commit comments

Comments
 (0)