myGLSLDefinitions = `
// ----------- OTHER LIBS -----------
${glslInverseFunctions}
${rngCode}
// ---------- COMMON VARIABLES -------
uniform sampler2D u_texture_transforms;
vec3 matCols[7];
vec3 matProbs[7];
vec3 matRatios[7]; // loss ratio
void initMaterials(){
matCols[0] = vec3(1.0, 0.89, 0.81);
matCols[1] = vec3(1.0, 0.90, 0.81);
matCols[2] = vec3(1.0,0.99,0.81);
matCols[3] = vec3(0.9,0.1,0.1);
matCols[4] = vec3(0.1,0.9,0.1);
matCols[5] = vec3(1.0,0.69,0.81);
matCols[6] = vec3(1.0,0.59,0.81);
matProbs[0] = vec3(0.5, 0.5, 0.0);
matProbs[1] = vec3(0.5, 0.5, 0.0);
matProbs[2] = vec3(0.5, 0.5, 0.0);
matProbs[3] = vec3(0.5, 0.5, 0.0);
matProbs[4] = vec3(0.5, 0.5, 0.0);
matProbs[5] = vec3(0.1, 0.2, 0.7);
matProbs[6] = vec3(0.3, 0.3, 0.3);
matRatios[0] = vec3(0.1, 0.5, 1.0);
matRatios[1] = vec3(0.1, 0.5, 1.0);
matRatios[2] = vec3(0.1, 0.5, 1.0);
matRatios[3] = vec3(0.1, 0.5, 1.0);
matRatios[4] = vec3(0.1, 0.5, 1.0);
matRatios[5] = vec3(0.1, 0.5, 1.0);
matRatios[6] = vec3(0.1, 0.5, 1.0);
}
// ---------- CONSTANTS ------------
const float EPSILON = 1e-5;
const float INFINITY = 1e5;
const float PI = 3.14159265358;
const int shadowEnabledIndex = 4;
const int numOfTransformations = 7;
// ---------- STRUCTS & FUNCTIONS -------------
struct ObjectFeatures
{
mat4 transform;
vec3 matColor;
vec3 matProbs;
float matRatio;
};
struct PhotonData
{
vec3 pos;
vec3 dir;
vec3 normal;
float power;
float state;
float hitMatchID;
};
struct Ray
{
vec3 origin;
vec3 direction;
float tMin;
float tMax;
};
vec3 pointOnRay(in Ray ray,float t){
return (ray.origin+t*ray.direction);
}
struct AABB{
vec3 minP;
vec3 maxP;
};
AABB cannonical_aabb = AABB(vec3(-0.5),vec3(0.5));
float calcMod(float a, float b){
return a - (b * floor(a/b)); // return a mod b
}
vec2 getDataTextureCoords(float x, float y, float width, float height){
return vec2( (x)/width, (y)/height );
}
/*
Calculates integer index of the given
normalized index (param: nval) on a normalized
dimension of expected length
*/
float getIntIndex(float nval, float length){
return calcMod(nval * length, length);
}
float getIntIndexFromTexcoord(float texcoordVal, float length){
return ((texcoordVal * length) - 0.5);
}
mat4 getTransform(int index){
vec4 col0 = texture2D(u_texture_transforms, getDataTextureCoords(0.5, float(index) + 0.5, 4.0, 7.0));
vec4 col1 = texture2D(u_texture_transforms, getDataTextureCoords(1.5, float(index) + 0.5, 4.0, 7.0));
vec4 col2 = texture2D(u_texture_transforms, getDataTextureCoords(2.5, float(index) + 0.5, 4.0, 7.0));
vec4 col3 = texture2D(u_texture_transforms, getDataTextureCoords(3.5, float(index) + 0.5, 4.0, 7.0));
return mat4(col0, col1, col2, col3);
}
Ray getRay(vec2 pixel, vec2 resolution, float fov, vec3 cameraEye, vec3 cameraU, vec3 cameraV, vec3 cameraW){
Ray ray;
ray.origin = cameraEye;
float height = 2.*tan(fov/2.);
float aspect = resolution.x/resolution.y;
float width = height*aspect;
vec2 windowDim = vec2(width,height);
vec2 pixelSize = windowDim/resolution;
vec2 delta = -0.5*windowDim + pixel*pixelSize;
ray.direction = normalize(-cameraW + cameraV*delta.y + cameraU*delta.x);
ray.tMin = 0.;
ray.tMax = INFINITY;
return ray;
}
bool insersectsRayAABB(inout Ray ray, AABB aabb) {
vec3 tMin = (aabb.minP.xyz - ray.origin) / ray.direction;
vec3 tMax = (aabb.maxP.xyz - ray.origin) / ray.direction;
vec3 t1 = min(tMin, tMax);
vec3 t2 = max(tMin, tMax);
//float tNear = max(max(max(t1.x, t1.y), t1.z),ray.tMin);
//float tFar = min(min(min(t2.x, t2.y), t2.z),ray.tMax);
float tNear = max(max(t1.x, t1.y), t1.z);
float tFar = min(min(t2.x, t2.y), t2.z);
if (tNear < tFar){
ray.tMin = tNear;
ray.tMax = tFar;
return true;
}
return false;
}
vec3 getNormal(AABB aabb,vec3 p){
vec3 c = (aabb.minP+aabb.maxP)/2.;
vec3 d = p-c;
vec3 v = abs(d);
int i = v.y > v.x ? ( v.z > v.y ? 2 : 1 ) : ( v.z > v.x ? 2 : 0 );
// Which Sign of the axis: The sign of the component selects the positive or negative direction.
return (i == 0) ? ((p.x>=0.)?vec3(1,0,0):vec3(-1,0,0)) :
(i == 1) ? ((p.y>=0.)?vec3(0,1,0):vec3(0,-1,0)) :
((p.z>=0.)?vec3(0,0,1):vec3(0,0,-1));
}
vec3 getNormalColor(AABB aabb,vec3 p, vec3 c1, vec3 c2, vec3 c3, vec3 c4, vec3 c5, vec3 c6){
vec3 c = (aabb.minP+aabb.maxP)/2.;
vec3 d = p-c;
vec3 v = abs(d);
int i = v.y > v.x ? ( v.z > v.y ? 2 : 1 ) : ( v.z > v.x ? 2 : 0 );
// Which Sign of the axis: The sign of the component selects the positive or negative direction.
return (i == 0) ? ((p.x>=0.)?c1:c2) :
(i == 1) ? ((p.y>=0.)?c3:c4) :
((p.z>=0.)?c5:c6);
}
bool insersectsRayCannonicalAABB(inout Ray ray) {
return insersectsRayAABB(ray, cannonical_aabb);
}
bool checkRayVsSphereCollision( vec3 origin, vec3 dir, vec3 center, float radius, inout float out_t){
vec3 O_C = origin - center;
float A = dot(dir,dir);
float B = 2.0 * dot( dir, O_C);
float D = dot(O_C, O_C) - (radius * radius);
if ((B * B - 4.0 * A * D) < 0.0){
return false; // not hitting Sphere
}
float det = sqrt(B * B - 4.0 * A * D);
// Far contact: float t1 = (0.0 - B + det) / (2.0 * A);
// Output the Near contact:
out_t = (0.0 - B - det) / (2.0 * A);
return true; // hitting the Sphere
}
// samplePosUV is such that -0.5 <= u,v <= 0.5
vec3 getRayDirection(vec2 samplePosOffset, vec2 delta, vec3 camU, vec3 camV, vec3 camW){
vec2 sampleDelta = delta + samplePosOffset;
return normalize(-camW + camV*sampleDelta.y + camU*sampleDelta.x);
}
struct AffineSquare
{
vec2 minPoint; // p0
vec2 p1;
vec2 maxPoint; // p2
vec2 p3;
};
AffineSquare GenerateAffineSquare(vec2 minPoint, vec2 maxPoint)
{
// Quadrilataral Affine Transformation of a Point
AffineSquare as;
as.minPoint = minPoint; // p0
as.p1 = vec2(maxPoint.x, minPoint.y);
as.maxPoint = maxPoint; // p2
as.p3 = vec2(minPoint.x, maxPoint.y);
return as;
}
vec2 getAffineUVPos(AffineSquare as, float u, float v)
{
return (1.0 - v) * ( (1.0 - u) * as.minPoint + u * as.p1 ) + v * ( (1.0 - u) * as.p3 + u * as.maxPoint );
}
vec3 getLightPosSample_Square(AffineSquare ASLight, float rnd_u, float rnd_v, float lightPosY)
{
vec2 this_randomlightpos2D = getAffineUVPos(ASLight, rnd_u, rnd_v);
return vec3(this_randomlightpos2D.x, lightPosY, this_randomlightpos2D.y);
}
struct RayCollisionOutput
{
float tmin; // collision tmin value
int matchID; // colliding object index
Ray matchInvRay; // colliding object's inverse transformation matrix
vec3 pos; // hitpos
vec3 normal; // hitnormal
vec3 matCol; // surface color
vec3 matProb;
vec3 matRatio;
};
// Used for both shadow test and ray-scene intersection
RayCollisionOutput detectNearestAABBCollision(vec3 rayOrigin, vec3 rayDirection){
// Storage of matching collision:
RayCollisionOutput retVal;
retVal.tmin = INFINITY; // collision tmin value
retVal.matchID = -1; // colliding object index
Ray ray = Ray(rayOrigin, rayDirection, 0.0, INFINITY);
// ---------Iterate over each object for collision-------
for(int i=0; i < numOfTransformations; i++){
//if (ignoreIdx != i){
Ray invRay = ray;
//invRay.direction = ray.direction;
mat4 mt = getTransform(i); // the transform
mat4 imt = inverse(mt); // inverse transform
// apply transform to ray
vec4 transformedRayOrigin = imt * vec4(invRay.origin, 1.0);
vec4 transformedRayDir = imt * vec4(invRay.direction, 0.0);
invRay.origin = transformedRayOrigin.xyz;
invRay.direction = transformedRayDir.xyz;
// compute tmin
if (insersectsRayCannonicalAABB(invRay)){
if(invRay.tMin < retVal.tmin){
retVal.tmin = invRay.tMin;
retVal.matchID = i;
retVal.matchInvRay = invRay;
vec3 q = pointOnRay(invRay, invRay.tMin); // hitpoint on cannonical scene
retVal.pos = pointOnRay(ray, invRay.tMin); // hitpoint on real scene
vec3 N = getNormal(cannonical_aabb, q); // normal on cannonical aabb
vec4 realN4 = getTransform(i) * vec4(N,0.0); // normal on real scene homogenous vector
retVal.normal = normalize(vec3(realN4[0], realN4[1], realN4[2])); // normal on real scene
retVal.matCol = matCols[i]; // color of surface
retVal.matProb = matProbs[i];
retVal.matRatio = matRatios[i];
}
}
//}
}
return retVal;
}
vec3 getRandomHemisphereSample(vec3 realNormal, vec3 hitpos, float randomZ, float randomPhi){
float r = sqrt(1.0 - randomZ * randomZ);
vec3 d = vec3(hitpos.x + r * cos(randomPhi), hitpos.y + r * sin(randomPhi), hitpos.z + randomZ);
//--find U,V,W such that Normal == W and U,V,W are orthogonal
vec3 tempVector = realNormal;
if (abs(realNormal.x) < abs(realNormal.y) && abs(realNormal.x) < abs(realNormal.z))
tempVector.x = 1.0;
else if (abs(realNormal.y) < abs(realNormal.x) && abs(realNormal.y) < abs(realNormal.z))
tempVector.y = 1.0;
else tempVector.z = 1.0;
vec3 U = normalize(cross(tempVector,realNormal));
vec3 V = cross(realNormal,U);
vec3 W = realNormal;
//--
vec3 dsample = vec3(dot(d, U) , dot(d, V), dot(d, W));
return normalize(dsample);
}
`