Skip to content

Instantly share code, notes, and snippets.

@erichlof
Last active April 20, 2022 15:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erichlof/e1fffe6006ef90d376331e300b3a1f2b to your computer and use it in GitHub Desktop.
Save erichlof/e1fffe6006ef90d376331e300b3a1f2b to your computer and use it in GitHub Desktop.
1-sided Rectangle area lights
precision highp float;
precision highp int;
precision highp sampler2D;
uniform sampler2D tTriangleTexture;
uniform sampler2D tAABBTexture;
#include <pathtracing_uniforms_and_defines>
uniform mat4 uLight0_Matrix;
uniform mat4 uLight1_Matrix;
uniform mat4 uLight0_InvMatrix;
uniform mat4 uLight1_InvMatrix;
uniform float uFogDensity;
uniform float uLight0Power;
uniform float uLight1Power;
//float InvTextureWidth = 0.000244140625; // (1 / 4096 texture width)
//float InvTextureWidth = 0.00048828125; // (1 / 2048 texture width)
//float InvTextureWidth = 0.0009765625; // (1 / 1024 texture width)
#define INV_TEXTURE_WIDTH 0.00048828125
#define N_RECTANGLES 2
//-----------------------------------------------------------------------
vec3 rayOrigin, rayDirection;
// recorded intersection data:
// vec3 hitNormal, hitEmission, hitColor;
vec2 hitUV;
// int hitType;
// float hitObjectID;
bool hitIsModel;
struct Rectangle
{
vec3 position;
vec3 normal;
float radiusU;
float radiusV;
vec3 emission;
vec3 color;
int type;
};
struct Sphere
{
float radius;
vec3 position;
vec3 emission;
vec3 color;
int type;
};
// struct Box { vec3 minCorner; vec3 maxCorner; vec3 emission; vec3 color; int type; };
Rectangle rectangles[N_RECTANGLES];
#include <pathtracing_random_functions>
#include <pathtracing_calc_fresnel_reflectance>
#include <pathtracing_sphere_intersect>
#include <pathtracing_boundingbox_intersect>
#include <pathtracing_bvhTriangle_intersect>
//#include <pathtracing_rectangle_intersect>
vec2 stackLevels[28];
//vec4 boxNodeData0 corresponds to .x = idTriangle, .y = aabbMin.x, .z = aabbMin.y, .w = aabbMin.z
//vec4 boxNodeData1 corresponds to .x = idRightChild .y = aabbMax.x, .z = aabbMax.y, .w = aabbMax.z
void GetBoxNodeData(const in float i, inout vec4 boxNodeData0, inout vec4 boxNodeData1)
{
// each bounding box's data is encoded in 2 rgba(or xyzw) texture slots
float ix2 = i * 2.0;
// (ix2 + 0.0) corresponds to .x = idTriangle, .y = aabbMin.x, .z = aabbMin.y, .w = aabbMin.z
// (ix2 + 1.0) corresponds to .x = idRightChild .y = aabbMax.x, .z = aabbMax.y, .w = aabbMax.z
ivec2 uv0 = ivec2(mod(ix2 + 0.0, 2048.0), (ix2 + 0.0) * INV_TEXTURE_WIDTH); // data0
ivec2 uv1 = ivec2(mod(ix2 + 1.0, 2048.0), (ix2 + 1.0) * INV_TEXTURE_WIDTH); // data1
boxNodeData0 = texelFetch(tAABBTexture, uv0, 0);
boxNodeData1 = texelFetch(tAABBTexture, uv1, 0);
}
vec3 randPointOnRectangle;
//----------------------------------------------------------------------------------------------------------------
float RectangleIntersect( vec3 pos, vec3 normal, float radiusU, float radiusV, vec3 rayOrigin, vec3 rayDirection )
//----------------------------------------------------------------------------------------------------------------
{
float dt = dot(-normal, rayDirection);
// use the following for one-sided rectangle
if (dt < 0.0) return INFINITY;
float t = dot(-normal, pos - rayOrigin) / dt;
if (t < 0.0) return INFINITY;
vec3 hit = rayOrigin + rayDirection * t;
vec3 vi = hit - pos;
vec3 U = normalize( cross( abs(normal.y) < 0.9 ? vec3(0, 1, 0) : vec3(0, 0, 1), normal ) );
vec3 V = cross(normal, U);
return (abs(dot(U, vi)) > radiusU || abs(dot(V, vi)) > radiusV) ? INFINITY : t;
}
vec3 sampleRectangleLight(vec3 x, vec3 nl, Rectangle light, out float weight)
{
// randPointOnRectangle has already been calculated in CalculateRadiance() function,
// so we can skip this next part
// vec3 U = normalize(cross( abs(light.normal.y) < 0.9 ? vec3(0, 1, 0) : vec3(0, 0, 1), light.normal));
// vec3 V = cross(light.normal, U);
// vec3 randPointOnLight = light.position;
// randPointOnLight += U * light.radiusU * (rng() * 2.0 - 1.0) * 0.9;
// randPointOnLight += V * light.radiusV * (rng() * 2.0 - 1.0) * 0.9;
// randPointOnLight = vec3(m * vec4(randPointOnLight, 1.0));
vec3 rotatedLightNormal;
if (light == rectangles[0])
rotatedLightNormal = normalize(vec3( uLight0_Matrix * vec4(light.normal, 0.0) ));
else if (light == rectangles[1])
rotatedLightNormal = normalize(vec3( uLight1_Matrix * vec4(light.normal, 0.0) ));
vec3 lightN = rotatedLightNormal;//dot(nl, rotatedLightNormal) < 0.0 ? rotatedLightNormal : -rotatedLightNormal;
vec3 dirToLight = randPointOnRectangle - x;
float r2 = (light.radiusU * 2.0) * (light.radiusV * 2.0);
float d2 = dot(dirToLight, dirToLight);
float cos_a_max = sqrt(1.0 - clamp( r2 / d2, 0.0, 1.0));
dirToLight = normalize(dirToLight);
float dotNlRayDir = max(0.0, dot(nl, dirToLight));
weight = 2.0 * (1.0 - cos_a_max) * max(0.0, -dot(dirToLight, lightN)) * dotNlRayDir;
weight = clamp(weight, 0.0, 1.0);
return dirToLight;
}
/* Credit: Some of the equi-angular sampling code is borrowed from https://www.shadertoy.com/view/Xdf3zB posted by user 'sjb' ,
// who in turn got it from the paper 'Importance Sampling Techniques for Path Tracing in Participating Media' ,
which can be viewed at: https://docs.google.com/viewer?url=https%3A%2F%2Fwww.solidangle.com%2Fresearch%2Fegsr2012_volume.pdf */
void sampleEquiAngular(float u, float maxDistance, vec3 rOrigin, vec3 rDirection, vec3 lightPos, out float dist, out float pdf)
{
// get coord of closest point to light along (infinite) ray
float delta = dot(lightPos - rOrigin, rDirection);
// get distance this point is from light
float D = distance(rOrigin + delta * rDirection, lightPos);
// get angle of endpoints
float thetaA = atan(0.0 - delta, D);
float thetaB = atan(maxDistance - delta, D);
// take sample
float t = D * tan(mix(thetaA, thetaB, u));
dist = delta + t;
pdf = D / ((thetaB - thetaA) * (D * D + t * t));
}
/* mat4 makeRotateX(float rot)
{
float s = sin(rot);
float c = cos(rot);
return mat4(
1, 0, 0, 0,
0, c, s, 0,
0,-s, c, 0,
0, 0, 0, 1
);
}
mat4 makeRotateY(float rot)
{
float s = sin(rot);
float c = cos(rot);
return mat4(
c, 0,-s, 0,
0, 1, 0, 0,
s, 0, c, 0,
0, 0, 0, 1
);
}
mat4 makeRotateZ(float rot)
{
float s = sin(rot);
float c = cos(rot);
return mat4(
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
} */
//-----------------------------------------------------------------------------------------------------------------------------------------------
float SceneIntersect(vec3 rOrigin, vec3 rDirection, out vec3 hitNormal, out vec3 hitEmission, out vec3 hitColor, out float hitObjectID, out int hitType)
//-----------------------------------------------------------------------------------------------------------------------------------------------
{
vec4 currentBoxNodeData0, nodeAData0, nodeBData0, tmpNodeData0;
vec4 currentBoxNodeData1, nodeAData1, nodeBData1, tmpNodeData1;
vec4 vd0, vd1, vd2, vd3, vd4, vd5, vd6, vd7;
vec3 inverseDir = 1.0 / rDirection;
vec3 rRotatedOrigin, rRotatedDirection;
vec2 currentStackData, stackDataA, stackDataB, tmpStackData;
ivec2 uv0, uv1, uv2, uv3, uv4, uv5, uv6, uv7;
float d;
float t = INFINITY;
float stackptr = 0.0;
float id = 0.0;
float tu, tv;
float triangleID = 0.0;
float triangleU = 0.0;
float triangleV = 0.0;
float triangleW = 0.0;
int objectCount = 0;
hitObjectID = -INFINITY;
bool skip = false;
bool triangleLookupNeeded = false;
hitIsModel = false;
// this part transforms the ray by the inverse of the matrix m (m holds the rectangle's transformations)
rRotatedOrigin = vec3( uLight0_InvMatrix * vec4(rOrigin, 1.0) );
rRotatedDirection = vec3( uLight0_InvMatrix * vec4(rDirection, 0.0) );
// NOTE: make sure to use rRotatedOrigin and rRotatedDirection (instead of the usual ray origin and direction) in the arguments to RectangleIntersect() below
d = RectangleIntersect( rectangles[0].position, rectangles[0].normal, rectangles[0].radiusU, rectangles[0].radiusV, rRotatedOrigin, rRotatedDirection ); // <----
if (d < t)
{
t = d;
hitNormal = rectangles[0].normal;
hitNormal = vec3( transpose(uLight0_InvMatrix) * vec4(hitNormal, 0.0) );
hitEmission = rectangles[0].emission;
hitColor = rectangles[0].color;
hitType = rectangles[0].type;
hitIsModel = false;
hitObjectID = float(objectCount);
}
objectCount++;
rRotatedOrigin = vec3( uLight1_InvMatrix * vec4(rOrigin, 1.0) );
rRotatedDirection = vec3( uLight1_InvMatrix * vec4(rDirection, 0.0) );
// NOTE: make sure to use rRotatedOrigin and rRotatedDirection (instead of the usual ray origin and direction) in the arguments to RectangleIntersect() below
d = RectangleIntersect( rectangles[1].position, rectangles[1].normal, rectangles[1].radiusU, rectangles[1].radiusV, rRotatedOrigin, rRotatedDirection ); // <----
if (d < t)
{
t = d;
hitNormal = rectangles[1].normal;
hitNormal = vec3( transpose(uLight1_InvMatrix) * vec4(hitNormal, 0.0) );
hitEmission = rectangles[1].emission;
hitColor = rectangles[1].color;
hitType = rectangles[1].type;
hitIsModel = false;
hitObjectID = float(objectCount);
}
objectCount++;
GetBoxNodeData(stackptr, currentBoxNodeData0, currentBoxNodeData1);
currentStackData = vec2(stackptr, BoundingBoxIntersect(currentBoxNodeData0.yzw, currentBoxNodeData1.yzw, rOrigin, inverseDir));
stackLevels[0] = currentStackData;
skip = (currentStackData.y < t);
while (true)
{
if (!skip)
{
// decrease pointer by 1 (0.0 is root level, 27.0 is maximum depth)
if (--stackptr < 0.0) // went past the root level, terminate loop
break;
currentStackData = stackLevels[int(stackptr)];
if (currentStackData.y >= t)
continue;
GetBoxNodeData(currentStackData.x, currentBoxNodeData0, currentBoxNodeData1);
}
skip = false; // reset skip
if (currentBoxNodeData0.x < 0.0) // < 0.0 signifies an inner node
{
GetBoxNodeData(currentStackData.x + 1.0, nodeAData0, nodeAData1);
GetBoxNodeData(currentBoxNodeData1.x, nodeBData0, nodeBData1);
stackDataA = vec2(currentStackData.x + 1.0, BoundingBoxIntersect(nodeAData0.yzw, nodeAData1.yzw, rOrigin, inverseDir));
stackDataB = vec2(currentBoxNodeData1.x, BoundingBoxIntersect(nodeBData0.yzw, nodeBData1.yzw, rOrigin, inverseDir));
// first sort the branch node data so that 'a' is the smallest
if (stackDataB.y < stackDataA.y)
{
tmpStackData = stackDataB;
stackDataB = stackDataA;
stackDataA = tmpStackData;
tmpNodeData0 = nodeBData0;
tmpNodeData1 = nodeBData1;
nodeBData0 = nodeAData0;
nodeBData1 = nodeAData1;
nodeAData0 = tmpNodeData0;
nodeAData1 = tmpNodeData1;
} // branch 'b' now has the larger rayT value of 'a' and 'b'
if (stackDataB.y < t) // see if branch 'b' (the larger rayT) needs to be processed
{
currentStackData = stackDataB;
currentBoxNodeData0 = nodeBData0;
currentBoxNodeData1 = nodeBData1;
skip = true; // this will prevent the stackptr from decreasing by 1
}
if (stackDataA.y < t) // see if branch 'a' (the smaller rayT) needs to be processed
{
if (skip) // if larger branch 'b' needed to be processed also,
stackLevels[int(stackptr++)] = stackDataB; // cue larger branch 'b' for future round
// also, increase pointer by 1
currentStackData = stackDataA;
currentBoxNodeData0 = nodeAData0;
currentBoxNodeData1 = nodeAData1;
skip = true; // this will prevent the stackptr from decreasing by 1
}
continue;
} // end if (currentBoxNodeData0.x < 0.0) // inner node
// else this is a leaf
// each triangle's data is encoded in 8 rgba(or xyzw) texture slots
id = 8.0 * currentBoxNodeData0.x;
uv0 = ivec2(mod(id + 0.0, 2048.0), (id + 0.0) * INV_TEXTURE_WIDTH);
uv1 = ivec2(mod(id + 1.0, 2048.0), (id + 1.0) * INV_TEXTURE_WIDTH);
uv2 = ivec2(mod(id + 2.0, 2048.0), (id + 2.0) * INV_TEXTURE_WIDTH);
vd0 = texelFetch(tTriangleTexture, uv0, 0);
vd1 = texelFetch(tTriangleTexture, uv1, 0);
vd2 = texelFetch(tTriangleTexture, uv2, 0);
d = BVH_TriangleIntersect(vec3(vd0.xyz), vec3(vd0.w, vd1.xy), vec3(vd1.zw, vd2.x), rOrigin, rDirection, tu, tv);
if (d < t)
{
t = d;
triangleID = id;
triangleU = tu;
triangleV = tv;
triangleLookupNeeded = true;
}
} // end while (true)
if (triangleLookupNeeded)
{
//uv0 = ivec2( mod(triangleID + 0.0, 2048.0), (triangleID + 0.0) * INV_TEXTURE_WIDTH );
//uv1 = ivec2( mod(triangleID + 1.0, 2048.0), (triangleID + 1.0) * INV_TEXTURE_WIDTH );
uv2 = ivec2(mod(triangleID + 2.0, 2048.0), (triangleID + 2.0) * INV_TEXTURE_WIDTH);
uv3 = ivec2(mod(triangleID + 3.0, 2048.0), (triangleID + 3.0) * INV_TEXTURE_WIDTH);
uv4 = ivec2(mod(triangleID + 4.0, 2048.0), (triangleID + 4.0) * INV_TEXTURE_WIDTH);
uv5 = ivec2(mod(triangleID + 5.0, 2048.0), (triangleID + 5.0) * INV_TEXTURE_WIDTH);
//uv6 = ivec2( mod(triangleID + 6.0, 2048.0), (triangleID + 6.0) * INV_TEXTURE_WIDTH );
//uv7 = ivec2( mod(triangleID + 7.0, 2048.0), (triangleID + 7.0) * INV_TEXTURE_WIDTH );
//vd0 = texelFetch(tTriangleTexture, uv0, 0);
//vd1 = texelFetch(tTriangleTexture, uv1, 0);
vd2 = texelFetch(tTriangleTexture, uv2, 0);
vd3 = texelFetch(tTriangleTexture, uv3, 0);
vd4 = texelFetch(tTriangleTexture, uv4, 0);
vd5 = texelFetch(tTriangleTexture, uv5, 0);
//vd6 = texelFetch(tTriangleTexture, uv6, 0);
//vd7 = texelFetch(tTriangleTexture, uv7, 0);
// face normal for flat-shaded polygon look
//hitNormal = normalize( cross(vec3(vd0.w, vd1.xy) - vec3(vd0.xyz), vec3(vd1.zw, vd2.x) - vec3(vd0.xyz)) );
// interpolated normal using triangle intersection's uv's
triangleW = 1.0 - triangleU - triangleV;
hitNormal = triangleW * vec3(vd2.yzw) + triangleU * vec3(vd3.xyz) + triangleV * vec3(vd3.w, vd4.xy);
hitEmission = vec3(0);
hitColor = vec3(1);//uMaterialColor;//vd6.yzw;
hitUV = triangleW * vec2(vd4.zw) + triangleU * vec2(vd5.xy) + triangleV * vec2(vd5.zw);
//hitType = int(uMaterialType);//int(vd6.x);
hitType = COAT;
//hitAlbedoTextureID = -1;//int(vd7.x);
hitIsModel = true;
hitObjectID = float(objectCount);
}
return t;
} // end float SceneIntersect( out bool finalIsRayExiting )
//----------------------------------------------------------------------------------------------------------------------------------------------------
vec3 CalculateRadiance(out vec3 objectNormal, out vec3 objectColor, out float objectID, out float pixelSharpness)
//----------------------------------------------------------------------------------------------------------------------------------------------------
{
Rectangle chosenRectangleLight;
vec3 cameraRayOrigin = rayOrigin;
vec3 cameraRayDirection = rayDirection;
vec3 vRayOrigin, vRayDirection;
// recorded intersection data (from eye):
vec3 eHitNormal, eHitEmission, eHitColor;
float eHitObjectID;
int eHitType = -100; // note: make sure to initialize this to a nonsense type id number!
// recorded intersection data (from volumetric particle):
vec3 vHitNormal, vHitEmission, vHitColor;
float vHitObjectID;
int vHitType = -100; // note: make sure to initialize this to a nonsense type id number!
vec3 accumCol = vec3(0);
vec3 mask = vec3(1);
// vec3 checkCol0 = vec3(1);
// vec3 checkCol1 = vec3(0.5);
vec3 lightVec;
vec3 particlePos;
vec3 tdir;
vec3 x, n, nl;
float t, vt, camt;
float u, xx;
float pdf;
float d;
float geomTerm;
float nc, nt, ratioIoR, Re, Tr;
float P, RP, TP;
float weight;
int diffuseCount = 0;
int previousIntersecType = -100;
// eHitType = -100;
bool coatTypeIntersected = false;
bool bounceIsSpecular = true;
bool sampleLight = false;
float trans;
vec3 lightPos;
vec3 dirToLight;
vec3 U0 = normalize(cross( abs(rectangles[0].normal.y) < 0.9 ? vec3(0, 1, 0) : vec3(0, 0, 1), rectangles[0].normal));
vec3 V0 = cross(rectangles[0].normal, U0);
vec3 U1 = normalize(cross( abs(rectangles[1].normal.y) < 0.9 ? vec3(0, 1, 0) : vec3(0, 0, 1), rectangles[1].normal));
vec3 V1 = cross(rectangles[1].normal, U1);
for (int bounces = 0; bounces < 5; bounces++)
{
previousIntersecType = eHitType;
// reset random point
randPointOnRectangle = vec3(0);
u = rng();
if (u < 0.5)
{
randPointOnRectangle += U0 * rectangles[0].radiusU * (rng() * 2.0 - 1.0) * 0.9;
randPointOnRectangle += V0 * rectangles[0].radiusV * (rng() * 2.0 - 1.0) * 0.9;
randPointOnRectangle = vec3(uLight0_Matrix * vec4(randPointOnRectangle, 1.0));
chosenRectangleLight = rectangles[0];
}
else
{
randPointOnRectangle += U1 * rectangles[1].radiusU * (rng() * 2.0 - 1.0) * 0.9;
randPointOnRectangle += V1 * rectangles[1].radiusV * (rng() * 2.0 - 1.0) * 0.9;
randPointOnRectangle = vec3(uLight1_Matrix * vec4(randPointOnRectangle, 1.0));
chosenRectangleLight = rectangles[1];
}
lightPos = randPointOnRectangle;
t = SceneIntersect(rayOrigin, rayDirection, eHitNormal, eHitEmission, eHitColor, eHitObjectID, eHitType);
// on first loop iteration, save intersection distance along camera ray (t) into camt variable for use below
if (bounces == 0)
{
camt = t;
//objectNormal = eHitNormal; // handled below
objectColor = eHitColor;
objectID = eHitObjectID;
}
// if(bounces == 0) {
// objectNormal = nl;
// objectColor = eHitColor;
// objectID = eHitObjectID;
// }
// sample along intial ray from camera into the scene
sampleEquiAngular(u, camt, cameraRayOrigin, cameraRayDirection, lightPos, xx, pdf);
// create a particle along cameraRay and cast a shadow ray towards light (similar to Direct Lighting)
particlePos = cameraRayOrigin + xx * cameraRayDirection;
lightVec = lightPos - particlePos;
d = length(lightVec);
vRayOrigin = particlePos;
vRayDirection = normalize(lightVec);
vt = SceneIntersect(vRayOrigin, vRayDirection, vHitNormal, vHitEmission, vHitColor, vHitObjectID, vHitType);
// if the particle can see the light source, apply volumetric lighting calculation
if (vHitType == LIGHT)
{
trans = exp( -((d + xx) * uFogDensity) );
geomTerm = 1.0 / (d * d);
accumCol += vHitEmission * geomTerm * trans / pdf;
}
// otherwise the particle will remain in shadow - this is what produces the shafts of light vs. the volume shadows
// useful data
n = normalize(eHitNormal);
nl = dot(n, rayDirection) < 0.0 ? n : -n;
x = rayOrigin + rayDirection * t;
if (diffuseCount == 0)
{
objectNormal = nl;
//objectColor = eHitColor; // handled above
//objectID = eHitObjectID; // handled above
}
if (eHitType == LIGHT)
{
if (bounceIsSpecular || sampleLight)
{
trans = exp(-((camt) * uFogDensity));
accumCol += mask * eHitEmission * trans;
}
// reached a light, so we can exit
break;
} // end if (hitType == LIGHT)
// uncomment this tiny block of code if you wish the background to be simple black (or fog color fading to black)
// no HDRI will be shown in the background
if (t == INFINITY)
break;
if (bounces == 1 && diffuseCount == 0 && !coatTypeIntersected)
{
objectNormal = nl;
}
// if we get here and sampleLight is still true, shadow ray failed to find a light source
if (sampleLight)
break;
if (eHitType == COAT) // Diffuse object underneath with ClearCoat on top (like car, or shiny pool ball)
{
coatTypeIntersected = true;
nc = 1.0; // IOR of Air
nt = 1.5; // IOR of Clear Coat
Re = calcFresnelReflectance(rayDirection, nl, nc, nt, ratioIoR);
Tr = 1.0 - Re;
P = 0.25 + (0.5 * Re);
RP = Re / P;
TP = Tr / (1.0 - P);
if (diffuseCount == 0 && rand() < P)
{
mask *= RP;
rayDirection = reflect(rayDirection, nl); // reflect ray from surface
rayOrigin = x + nl * uEPS_intersect;
continue;
}
diffuseCount++;
mask *= eHitColor;
mask *= TP;
bounceIsSpecular = false;
if (diffuseCount == 1 && rand() < 0.5)
{
//mask *= 2.0;
// choose random Diffuse sample vector
rayDirection = randomCosWeightedDirectionInHemisphere(nl);
rayOrigin = x + nl * uEPS_intersect;
continue;
}
dirToLight = sampleRectangleLight(x, nl, chosenRectangleLight, weight);
// since we only selected 1 light source by random choice, but there are 2 light sources (much brighter total)..
// we must up-weight the contribution of the light that we did end up picking
//weight *= 2.0; // 2.0 = number of light source choices (rectangles[0] or rectangles[1])
// the following line also upweights because there was 0.5 chance that we reflect off of clearCoat, or sample diffuse surface beneath the clearCoat
//mask *= diffuseCount == 1 ? 2.0 : 1.0; // multiply by number of choices: 2.0 (either specular reflection from ClearCoat surface layer, or diffuse reflection)
mask *= weight;
rayDirection = dirToLight;
rayOrigin = x + nl * uEPS_intersect;
sampleLight = true;
continue;
} //end if (hitType == COAT)
} // end for (int bounces = 0; bounces < 5; bounces++)
return max(vec3(0), accumCol);
} // end vec3 CalculateRadiance( out vec3 objectNormal, out vec3 objectColor, out float objectID, out float pixelSharpness )
//-----------------------------------------------------------------------
void SetupScene(void)
//-----------------------------------------------------------------------
{
vec3 z = vec3(0);
vec3 L0 = vec3(1.0, 0.05, 1.0) * uLight0Power;// Bright Pinkish light
vec3 L1 = vec3(0.05, 0.05, 1.0) * uLight1Power;// Bright Blueish light
// NOTE: make sure to define this rectangle in object space, position = vec3(0) and its normal points in the +Z direction = vec3(0,0,1)
rectangles[0] = Rectangle(vec3(0), vec3(0,0,1), 2.0, 100.0, L0, z, LIGHT);// Pink Rectangle Area Light
rectangles[1] = Rectangle(vec3(0), vec3(0,0,1), 1.0, 50.0, L1, z, LIGHT);// Blue Rectangle Area Light
}
#include <pathtracing_main>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment