Basic path-trace renderer pipeline.
This commit is contained in:
parent
ed6f725944
commit
bbd7ee2353
171
Sources/cycles/trait/PathTracer.hx
Normal file
171
Sources/cycles/trait/PathTracer.hx
Normal file
|
@ -0,0 +1,171 @@
|
|||
package cycles.trait;
|
||||
|
||||
import lue.Eg;
|
||||
import lue.math.Mat4;
|
||||
import lue.math.Vec4;
|
||||
import lue.trait.Trait;
|
||||
import lue.node.Transform;
|
||||
import lue.node.RootNode;
|
||||
import lue.resource.MaterialResource.MaterialContext;
|
||||
|
||||
class PathTracer extends Trait {
|
||||
|
||||
var context:MaterialContext;
|
||||
var eyeLocation:Int;
|
||||
var lightLocation:Int;
|
||||
var ray00Location:Int;
|
||||
var ray01Location:Int;
|
||||
var ray10Location:Int;
|
||||
var ray11Location:Int;
|
||||
|
||||
var objectLocations:Array<Int>;
|
||||
var transformMap:Map<Int, Transform>;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
requestInit(init);
|
||||
requestUpdate(update);
|
||||
}
|
||||
|
||||
function init() {
|
||||
context = Eg.getMaterialResource('pt_material').getContext('pt_trace_pass');
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "eye",
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
eyeLocation = context.resource.bind_constants.length - 1;
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "light",
|
||||
vec3: [0.9, 0.6, 1.1]
|
||||
}
|
||||
);
|
||||
lightLocation = context.resource.bind_constants.length - 1;
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "glossiness",
|
||||
float: 0.6
|
||||
}
|
||||
);
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "ray00",
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
ray00Location = context.resource.bind_constants.length - 1;
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "ray01",
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
ray01Location = context.resource.bind_constants.length - 1;
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "ray10",
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
ray10Location = context.resource.bind_constants.length - 1;
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "ray11",
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
ray11Location = context.resource.bind_constants.length - 1;
|
||||
|
||||
objectLocations = [];
|
||||
transformMap = new Map();
|
||||
var sphereNum = 0;
|
||||
for (n in RootNode.models) {
|
||||
if (n.id.split(".")[0] == "Sphere") {
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "sphereCenter" + sphereNum,
|
||||
vec3: [0.0, 0.0, 0.0]
|
||||
}
|
||||
);
|
||||
|
||||
var loc = context.resource.bind_constants.length - 1;
|
||||
objectLocations.push(loc);
|
||||
transformMap.set(loc, n.transform);
|
||||
|
||||
context.resource.bind_constants.push(
|
||||
{
|
||||
id: "sphereRadius" + sphereNum,
|
||||
float: 0.288
|
||||
}
|
||||
);
|
||||
|
||||
sphereNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var camera = RootNode.cameras[0];
|
||||
var eye = camera.transform.pos;
|
||||
|
||||
//var jitter = Mat4.identity();
|
||||
//jitter.initTranslate(Math.random() * 2 - 1, Math.random() * 2 - 1, 0);
|
||||
//jitter.multiplyScalar(1 / lue.App.w);
|
||||
var mvp = Mat4.identity();
|
||||
mvp.mult2(camera.V);
|
||||
mvp.mult2(camera.P);
|
||||
var inverse = Mat4.identity();
|
||||
// jitter.mult2(mvp);
|
||||
inverse.inverse2(mvp);
|
||||
var matrix = inverse;
|
||||
|
||||
// Set uniforms
|
||||
context.resource.bind_constants[eyeLocation].vec3 = [eye.x, eye.y, eye.z];
|
||||
|
||||
var v = getEyeRay(matrix, -1, -1, eye);
|
||||
context.resource.bind_constants[ray00Location].vec3 = [v.x, v.y, v.z];
|
||||
|
||||
var v = getEyeRay(matrix, -1, 1, eye);
|
||||
context.resource.bind_constants[ray01Location].vec3 = [v.x, v.y, v.z];
|
||||
|
||||
var v = getEyeRay(matrix, 1, -1, eye);
|
||||
context.resource.bind_constants[ray10Location].vec3 = [v.x, v.y, v.z];
|
||||
|
||||
var v = getEyeRay(matrix, 1, 1, eye);
|
||||
context.resource.bind_constants[ray11Location].vec3 = [v.x, v.y, v.z];
|
||||
|
||||
for (loc in objectLocations) {
|
||||
var t:Transform = transformMap.get(loc);
|
||||
context.resource.bind_constants[loc].vec3[0] = t.absx();
|
||||
context.resource.bind_constants[loc].vec3[1] = t.absy();
|
||||
context.resource.bind_constants[loc].vec3[2] = t.absz();
|
||||
}
|
||||
}
|
||||
|
||||
function getEyeRay(matrix:Mat4, x:Float, y:Float, eye:Vec4):Vec4 {
|
||||
var v = new Vec4();
|
||||
var vv = new kha.math.FastVector4(x, y, 0, 1);
|
||||
vv = matrix.multvec(vv);
|
||||
v.x = vv.x;
|
||||
v.y = vv.y;
|
||||
v.z = vv.z;
|
||||
v.w = vv.w;
|
||||
v.x /= v.w;
|
||||
v.y /= v.w;
|
||||
v.z /= v.w;
|
||||
v.w /= v.w;
|
||||
v.sub(eye);
|
||||
return v;
|
||||
}
|
||||
}
|
418
blender/path_tracer.py
Normal file
418
blender/path_tracer.py
Normal file
|
@ -0,0 +1,418 @@
|
|||
# Based on WebGL Path Tracing by Evan Wallace
|
||||
# (http://madebyevan.com/webgl-path-tracing/)
|
||||
|
||||
import bpy
|
||||
import os
|
||||
|
||||
|
||||
bounces = '5'
|
||||
epsilon = '0.0001'
|
||||
infinity = '10000.0'
|
||||
lightSize = 0.1
|
||||
lightVal = 0.5
|
||||
|
||||
objects = None
|
||||
sampleCount = 0
|
||||
|
||||
MATERIAL_DIFFUSE = 0
|
||||
MATERIAL_MIRROR = 1
|
||||
MATERIAL_GLOSSY = 2
|
||||
material = MATERIAL_MIRROR
|
||||
|
||||
YELLOW_BLUE_CORNELL_BOX = 0
|
||||
RED_GREEN_CORNELL_BOX = 1
|
||||
environment = YELLOW_BLUE_CORNELL_BOX
|
||||
|
||||
|
||||
def concat(objects, func):
|
||||
text = ''
|
||||
for i in range(0, len(objects)):
|
||||
text += func(objects[i])
|
||||
return text
|
||||
|
||||
|
||||
tracerFragmentSourceHeader = """
|
||||
#version 450
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
in vec3 initialRay;
|
||||
in vec2 texCoord;
|
||||
uniform vec3 eye;
|
||||
//uniform float textureWeight;
|
||||
uniform float timeSinceStart;
|
||||
//uniform sampler2D stexture;
|
||||
uniform float glossiness;
|
||||
vec3 roomCubeMin = vec3(-1.0, -1.0, -1.0);
|
||||
vec3 roomCubeMax = vec3(1.0, 1.0, 1.0);
|
||||
"""
|
||||
|
||||
|
||||
# compute the near and far intersections of the cube (stored in the x and y components) using the slab method
|
||||
# no intersection means vec.x > vec.y (really tNear > tFar)
|
||||
intersectCubeSource = """
|
||||
vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeMin, vec3 cubeMax) {
|
||||
vec3 tMin = (cubeMin - origin) / ray;
|
||||
vec3 tMax = (cubeMax - origin) / ray;
|
||||
vec3 t1 = min(tMin, tMax);
|
||||
vec3 t2 = max(tMin, tMax);
|
||||
float tNear = max(max(t1.x, t1.y), t1.z);
|
||||
float tFar = min(min(t2.x, t2.y), t2.z);
|
||||
return vec2(tNear, tFar);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# given that hit is a point on the cube, what is the surface normal?
|
||||
# TODO: do this with fewer branches
|
||||
normalForCubeSource = """
|
||||
vec3 normalForCube(vec3 hit, vec3 cubeMin, vec3 cubeMax) {
|
||||
if (hit.x < cubeMin.x + """ + epsilon + """) return vec3(-1.0, 0.0, 0.0);
|
||||
else if (hit.x > cubeMax.x - """ + epsilon + """) return vec3(1.0, 0.0, 0.0);
|
||||
else if (hit.y < cubeMin.y + """ + epsilon + """) return vec3(0.0, -1.0, 0.0);
|
||||
else if (hit.y > cubeMax.y - """ + epsilon + """) return vec3(0.0, 1.0, 0.0);
|
||||
else if (hit.z < cubeMin.z + """ + epsilon + """) return vec3(0.0, 0.0, -1.0);
|
||||
//else return vec3(0.0, 0.0, 1.0);
|
||||
return vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# compute the near intersection of a sphere
|
||||
# no intersection returns a value of +infinity
|
||||
intersectSphereSource = """
|
||||
float intersectSphere(vec3 origin, vec3 ray, vec3 sphereCenter, float sphereRadius) {
|
||||
vec3 toSphere = origin - sphereCenter;
|
||||
float a = dot(ray, ray);
|
||||
float b = 2.0 * dot(toSphere, ray);
|
||||
float c = dot(toSphere, toSphere) - sphereRadius*sphereRadius;
|
||||
float discriminant = b*b - 4.0*a*c;
|
||||
if (discriminant > 0.0) {
|
||||
float t = (-b - sqrt(discriminant)) / (2.0 * a);
|
||||
if (t > 0.0) return t;
|
||||
}
|
||||
return """ + infinity + """;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# given that hit is a point on the sphere, what is the surface normal?
|
||||
normalForSphereSource = """
|
||||
vec3 normalForSphere(vec3 hit, vec3 sphereCenter, float sphereRadius) {
|
||||
return (hit - sphereCenter) / sphereRadius;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# random cosine-weighted distributed vector
|
||||
# from http://www.rorydriscoll.com/2009/01/07/better-sampling/
|
||||
cosineWeightedDirectionSource = """
|
||||
vec3 cosineWeightedDirection(float seed, vec3 normal) {
|
||||
float u = random(vec3(12.9898, 78.233, 151.7182), seed);
|
||||
float v = random(vec3(63.7264, 10.873, 623.6736), seed);
|
||||
float r = sqrt(u);
|
||||
float angle = 6.283185307179586 * v;
|
||||
// compute basis from normal
|
||||
vec3 sdir, tdir;
|
||||
if (abs(normal.x) < 0.5) {
|
||||
sdir = cross(normal, vec3(1.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
sdir = cross(normal, vec3(0.0, 1.0, 0.0));
|
||||
}
|
||||
tdir = cross(normal, sdir);
|
||||
return r*cos(angle)*sdir + r*sin(angle)*tdir + sqrt(1.0-u)*normal;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# use the fragment position for randomness
|
||||
randomSource = """
|
||||
float random(vec3 scale, float seed) {
|
||||
return fract(sin(dot(texCoord.xyx + seed, scale)) * 43758.5453 + seed);
|
||||
// return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# random normalized vector
|
||||
uniformlyRandomDirectionSource = """
|
||||
vec3 uniformlyRandomDirection(float seed) {
|
||||
float u = random(vec3(12.9898, 78.233, 151.7182), seed);
|
||||
float v = random(vec3(63.7264, 10.873, 623.6736), seed);
|
||||
float z = 1.0 - 2.0 * u;
|
||||
float r = sqrt(1.0 - z * z);
|
||||
float angle = 6.283185307179586 * v;
|
||||
return vec3(r * cos(angle), r * sin(angle), z);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# random vector in the unit sphere
|
||||
# note: this is probably not statistically uniform, saw raising to 1/3 power somewhere but that looks wrong?
|
||||
uniformlyRandomVectorSource = """
|
||||
vec3 uniformlyRandomVector(float seed) {
|
||||
return uniformlyRandomDirection(seed) * sqrt(random(vec3(36.7539, 50.3658, 306.2759), seed));
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
# compute specular lighting contribution
|
||||
specularReflection = """
|
||||
vec3 reflectedLight = normalize(reflect(light - hit, normal));
|
||||
specularHighlight = max(0.0, dot(reflectedLight, normalize(hit - origin)));"""
|
||||
|
||||
|
||||
# update ray using normal and bounce according to a diffuse reflection
|
||||
newDiffuseRay = """
|
||||
ray = cosineWeightedDirection(time + float(bounce), normal);"""
|
||||
|
||||
|
||||
# update ray using normal according to a specular reflection
|
||||
newReflectiveRay = """
|
||||
ray = reflect(ray, normal);
|
||||
""" + specularReflection + """
|
||||
specularHighlight = 2.0 * pow(specularHighlight, 20.0);"""
|
||||
|
||||
|
||||
# update ray using normal and bounce according to a glossy reflection
|
||||
newGlossyRay = """
|
||||
ray = normalize(reflect(ray, normal)) + uniformlyRandomVector(time + float(bounce)) * glossiness;
|
||||
""" + specularReflection + """
|
||||
specularHighlight = pow(specularHighlight, 3.0);"""
|
||||
|
||||
|
||||
yellowBlueCornellBox = """
|
||||
if (hit.x < -0.9999) surfaceColor = vec3(0.1, 0.5, 1.0); // blue
|
||||
else if (hit.x > 0.9999) surfaceColor = vec3(1.0, 0.9, 0.1); // yellow"""
|
||||
|
||||
|
||||
redGreenCornellBox = """
|
||||
if (hit.x < -0.9999) surfaceColor = vec3(1.0, 0.3, 0.1); // red
|
||||
else if (hit.x > 0.9999) surfaceColor = vec3(0.3, 1.0, 0.1); // green"""
|
||||
|
||||
|
||||
def _getShadowTestCode(o):
|
||||
return o.getShadowTestCode()
|
||||
|
||||
|
||||
def makeShadow(objects):
|
||||
return """
|
||||
float shadow(vec3 origin, vec3 ray) {
|
||||
""" + concat(objects, _getShadowTestCode) + """
|
||||
return 1.0;
|
||||
}"""
|
||||
|
||||
|
||||
def _getIntersectCode(o):
|
||||
return o.getIntersectCode()
|
||||
|
||||
|
||||
def _getMinimumIntersectCode(o):
|
||||
return o.getMinimumIntersectCode()
|
||||
|
||||
|
||||
def _getNormalCalculationCode(o):
|
||||
return o.getNormalCalculationCode()
|
||||
|
||||
|
||||
def makeCalculateColor(objects):
|
||||
return """
|
||||
vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
|
||||
vec3 colorMask = vec3(1.0);
|
||||
vec3 accumulatedColor = vec3(0.0);
|
||||
|
||||
// main raytracing loop
|
||||
for (int bounce = 0; bounce < """ + bounces + """; bounce++) {
|
||||
// compute the intersection with everything
|
||||
vec2 tRoom = intersectCube(origin, ray, roomCubeMin, roomCubeMax);
|
||||
""" + concat(objects, _getIntersectCode) + """
|
||||
|
||||
// find the closest intersection
|
||||
float t = """ + infinity + """;
|
||||
if (tRoom.x < tRoom.y) t = tRoom.y;
|
||||
""" + concat(objects, _getMinimumIntersectCode) + """
|
||||
|
||||
// info about hit
|
||||
vec3 hit = origin + ray * t;
|
||||
vec3 surfaceColor = vec3(0.75);
|
||||
float specularHighlight = 0.0;
|
||||
vec3 normal;
|
||||
|
||||
// calculate the normal (and change wall color)
|
||||
if (t == tRoom.y) {
|
||||
normal = -normalForCube(hit, roomCubeMin, roomCubeMax);
|
||||
""" + [yellowBlueCornellBox, redGreenCornellBox][environment] + """
|
||||
""" + newDiffuseRay + """
|
||||
}
|
||||
else if (t == """ + infinity + """) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int aa = 0;
|
||||
if (aa == 1) {aa = 0;} // hack to discard the first 'else' in 'else if'
|
||||
""" + concat(objects, _getNormalCalculationCode) + """
|
||||
""" + [newDiffuseRay, newReflectiveRay, newGlossyRay][material] + """
|
||||
}
|
||||
|
||||
// compute diffuse lighting contribution
|
||||
vec3 toLight = light - hit;
|
||||
float diffuse = max(0.0, dot(normalize(toLight), normal));
|
||||
|
||||
// trace a shadow ray to the light
|
||||
float shadowIntensity = shadow(hit + normal * """ + epsilon + """, toLight);
|
||||
|
||||
// do light bounce
|
||||
colorMask *= surfaceColor;
|
||||
accumulatedColor += colorMask * (""" + str(lightVal) + """ * diffuse * shadowIntensity);
|
||||
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
|
||||
|
||||
// calculate next origin
|
||||
origin = hit;
|
||||
}
|
||||
|
||||
return accumulatedColor;
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def makeMain():
|
||||
return """
|
||||
void main() {
|
||||
float time = timeSinceStart;
|
||||
vec3 col = vec3(0.0);
|
||||
const int samples = 1;
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
vec3 newLight = light + uniformlyRandomVector(time - 53.0) * """ + str(lightSize) + """;
|
||||
col += calculateColor(time, eye, initialRay, newLight);
|
||||
time += 0.35;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(vec3(col / samples), 1.0);
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def _getGlobalCode(o):
|
||||
return o.getGlobalCode()
|
||||
|
||||
|
||||
def makeTracerFragmentSource(objects):
|
||||
return tracerFragmentSourceHeader + \
|
||||
concat(objects, _getGlobalCode) + \
|
||||
intersectCubeSource + \
|
||||
normalForCubeSource + \
|
||||
intersectSphereSource + \
|
||||
normalForSphereSource + \
|
||||
randomSource + \
|
||||
cosineWeightedDirectionSource + \
|
||||
uniformlyRandomDirectionSource + \
|
||||
uniformlyRandomVectorSource + \
|
||||
makeShadow(objects) + \
|
||||
makeCalculateColor(objects) + \
|
||||
makeMain()
|
||||
|
||||
|
||||
class Sphere:
|
||||
def __init__(self, center, radius, id):
|
||||
self.center = center;
|
||||
self.radius = radius;
|
||||
self.centerStr = 'sphereCenter' + str(id);
|
||||
self.radiusStr = 'sphereRadius' + str(id);
|
||||
self.intersectStr = 'tSphere' + str(id);
|
||||
|
||||
def getGlobalCode(self):
|
||||
return """
|
||||
uniform vec3 """ + self.centerStr + """;
|
||||
uniform float """ + self.radiusStr + """;"""
|
||||
|
||||
def getIntersectCode(self):
|
||||
return """
|
||||
float """ + self.intersectStr + """ = intersectSphere(origin, ray, """ + self.centerStr + """, """ + self.radiusStr + """);"""
|
||||
|
||||
def getShadowTestCode(self):
|
||||
return """
|
||||
""" + self.getIntersectCode() + """
|
||||
if (""" + self.intersectStr + """ < 1.0) return 0.0;"""
|
||||
|
||||
def getMinimumIntersectCode(self):
|
||||
return """
|
||||
if (""" + self.intersectStr + """ < t) t = """ + self.intersectStr + """;"""
|
||||
|
||||
def getNormalCalculationCode(self):
|
||||
return """
|
||||
else if (t == """ + self.intersectStr + """) normal = normalForSphere(hit, """ + self.centerStr + """, """ + self.radiusStr + """);"""
|
||||
|
||||
|
||||
class Cube:
|
||||
def __init__(self, minCorner, maxCorner, id):
|
||||
self.minCorner = minCorner;
|
||||
self.maxCorner = maxCorner;
|
||||
self.minStr = 'cubeMin' + str(id);
|
||||
self.maxStr = 'cubeMax' + str(id);
|
||||
self.intersectStr = 'tCube' + str(id);
|
||||
|
||||
def getGlobalCode(self):
|
||||
return """
|
||||
uniform vec3 """ + self.minStr + """;
|
||||
uniform vec3 """ + self.maxStr + """;"""
|
||||
|
||||
def getIntersectCode(self):
|
||||
return """
|
||||
vec2 """ + self.intersectStr + """ = intersectCube(origin, ray, """ + self.minStr + """, """ + self.maxStr + """);"""
|
||||
|
||||
def getShadowTestCode(self):
|
||||
return """
|
||||
""" + self.getIntersectCode() + """
|
||||
if (""" + self.intersectStr + """.x > 0.0 && """ + self.intersectStr + """.x < 1.0 && """ + self.intersectStr + """.x < """ + self.intersectStr + """.y) return 0.0;"""
|
||||
|
||||
def getMinimumIntersectCode(self):
|
||||
return """
|
||||
if (""" + self.intersectStr + """.x > 0.0 && """ + self.intersectStr + """.x < """ + self.intersectStr + """.y && """ + self.intersectStr + """.x < t) t = """ + self.intersectStr + """.x;"""
|
||||
|
||||
def getNormalCalculationCode(self):
|
||||
return """
|
||||
// have to compare intersectStr.x < intersectStr.y otherwise two coplanar
|
||||
// cubes will look wrong (one cube will "steal" the hit from the other)
|
||||
else if (t == """ + self.intersectStr + """.x && """ + self.intersectStr + """.x < """ + self.intersectStr + """.y) normal = normalForCube(hit, """ + self.minStr + """, """ + self.maxStr + """);"""
|
||||
|
||||
|
||||
class Light:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def getGlobalCode(self):
|
||||
return """uniform vec3 light;"""
|
||||
|
||||
def getIntersectCode(self):
|
||||
return """"""
|
||||
|
||||
def getShadowTestCode(self):
|
||||
return """"""
|
||||
|
||||
def getMinimumIntersectCode(self):
|
||||
return """"""
|
||||
|
||||
def getNormalCalculationCode(self):
|
||||
return """"""
|
||||
|
||||
|
||||
def initObjects():
|
||||
nextObjectId = 0
|
||||
objects = []
|
||||
objects.append(Light())
|
||||
|
||||
for o in bpy.context.scene.objects:
|
||||
if o.name.split('.', 1)[0] == 'Sphere':
|
||||
objects.append(Sphere([0, 0, 0], 0, nextObjectId))
|
||||
nextObjectId += 1
|
||||
|
||||
return objects
|
||||
|
||||
objects = initObjects()
|
||||
|
||||
|
||||
def compile(frag_path):
|
||||
with open(frag_path, 'w') as f:
|
||||
f.write(makeTracerFragmentSource(objects))
|
|
@ -13,6 +13,7 @@ import write_data
|
|||
import nodes_logic
|
||||
import nodes_pipeline
|
||||
import nodes_world
|
||||
import path_tracer
|
||||
from armory import ArmoryExporter
|
||||
|
||||
def defaultSettings():
|
||||
|
@ -119,7 +120,8 @@ def exportGameData():
|
|||
# TODO: cache
|
||||
nodes_logic.buildNodeTrees()
|
||||
nodes_pipeline.buildNodeTrees(shader_references, asset_references)
|
||||
nodes_world.buildNodeTrees(shader_references, asset_references) # TODO: Have to build nodes everytime to collect env map resources, should be cached
|
||||
# TODO: Have to build nodes everytime to collect env map resources, should be cached
|
||||
nodes_world.buildNodeTrees(shader_references, asset_references)
|
||||
|
||||
# TODO: Set armatures to center of world so skin transform is zero
|
||||
armatures = []
|
||||
|
@ -188,6 +190,10 @@ def buildProject(self, build_type=0):
|
|||
fp = os.path.sep.join(s)
|
||||
os.chdir(fp)
|
||||
|
||||
# Compile path tracer shaders
|
||||
if len(bpy.data.cameras) > 0 and bpy.data.cameras[0].pipeline_path == 'pathtrace_pipeline':
|
||||
path_tracer.compile(raw_path + 'pt_trace_pass/pt_trace_pass.frag.glsl')
|
||||
|
||||
# Compile shaders if needed
|
||||
if os.path.isdir("compiled") == False:
|
||||
os.chdir(raw_path)
|
||||
|
|
|
@ -15,14 +15,22 @@ os.chdir('../env_map')
|
|||
make_resources.make('env_map.shader.json')
|
||||
make_variants.make('env_map.shader.json')
|
||||
|
||||
os.chdir('../ssao_pass')
|
||||
make_resources.make('ssao_pass.shader.json')
|
||||
make_variants.make('ssao_pass.shader.json')
|
||||
# os.chdir('../ssao_pass')
|
||||
# make_resources.make('ssao_pass.shader.json')
|
||||
# make_variants.make('ssao_pass.shader.json')
|
||||
|
||||
os.chdir('../blur_pass')
|
||||
make_resources.make('blur_pass.shader.json')
|
||||
make_variants.make('blur_pass.shader.json')
|
||||
# os.chdir('../blur_pass')
|
||||
# make_resources.make('blur_pass.shader.json')
|
||||
# make_variants.make('blur_pass.shader.json')
|
||||
|
||||
os.chdir('../combine_pass')
|
||||
make_resources.make('combine_pass.shader.json')
|
||||
make_variants.make('combine_pass.shader.json')
|
||||
# os.chdir('../combine_pass')
|
||||
# make_resources.make('combine_pass.shader.json')
|
||||
# make_variants.make('combine_pass.shader.json')
|
||||
|
||||
os.chdir('../pt_trace_pass')
|
||||
make_resources.make('pt_trace_pass.shader.json')
|
||||
make_variants.make('pt_trace_pass.shader.json')
|
||||
|
||||
os.chdir('../pt_final_pass')
|
||||
make_resources.make('pt_final_pass.shader.json')
|
||||
make_variants.make('pt_final_pass.shader.json')
|
||||
|
|
14
raw/pt_final_pass/pt_final_pass.frag.glsl
Normal file
14
raw/pt_final_pass/pt_final_pass.frag.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
#version 450
|
||||
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform sampler2D gbuffer;
|
||||
|
||||
in vec2 texCoord;
|
||||
|
||||
void main() {
|
||||
vec3 col = texture(gbuffer, texCoord).rgb;
|
||||
gl_FragColor = vec4(col, 1.0);
|
||||
}
|
33
raw/pt_final_pass/pt_final_pass.shader.json
Executable file
33
raw/pt_final_pass/pt_final_pass.shader.json
Executable file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"contexts": [
|
||||
{
|
||||
"id": "pt_final_pass",
|
||||
"params": [
|
||||
{
|
||||
"id": "depth_write",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"id": "compare_mode",
|
||||
"value": "always"
|
||||
},
|
||||
{
|
||||
"id": "cull_mode",
|
||||
"value": "none"
|
||||
},
|
||||
{
|
||||
"id": "blend_source",
|
||||
"value": "blend_one"
|
||||
},
|
||||
{
|
||||
"id": "blend_destination",
|
||||
"value": "blend_zero"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "pt_final_pass.vert.glsl",
|
||||
"fragment_shader": "pt_final_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
18
raw/pt_final_pass/pt_final_pass.vert.glsl
Normal file
18
raw/pt_final_pass/pt_final_pass.vert.glsl
Normal file
|
@ -0,0 +1,18 @@
|
|||
#version 450
|
||||
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
out vec2 texCoord;
|
||||
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
texCoord = pos.xy * madd + madd;
|
||||
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
408
raw/pt_trace_pass/pt_trace_pass.frag.glsl
Normal file
408
raw/pt_trace_pass/pt_trace_pass.frag.glsl
Normal file
|
@ -0,0 +1,408 @@
|
|||
|
||||
#version 450
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
in vec3 initialRay;
|
||||
in vec2 texCoord;
|
||||
uniform vec3 eye;
|
||||
//uniform float textureWeight;
|
||||
uniform float timeSinceStart;
|
||||
//uniform sampler2D stexture;
|
||||
uniform float glossiness;
|
||||
vec3 roomCubeMin = vec3(-1.0, -1.0, -1.0);
|
||||
vec3 roomCubeMax = vec3(1.0, 1.0, 1.0);
|
||||
uniform vec3 light;
|
||||
uniform vec3 sphereCenter0;
|
||||
uniform float sphereRadius0;
|
||||
uniform vec3 sphereCenter1;
|
||||
uniform float sphereRadius1;
|
||||
uniform vec3 sphereCenter2;
|
||||
uniform float sphereRadius2;
|
||||
uniform vec3 sphereCenter3;
|
||||
uniform float sphereRadius3;
|
||||
uniform vec3 sphereCenter4;
|
||||
uniform float sphereRadius4;
|
||||
uniform vec3 sphereCenter5;
|
||||
uniform float sphereRadius5;
|
||||
uniform vec3 sphereCenter6;
|
||||
uniform float sphereRadius6;
|
||||
uniform vec3 sphereCenter7;
|
||||
uniform float sphereRadius7;
|
||||
uniform vec3 sphereCenter8;
|
||||
uniform float sphereRadius8;
|
||||
uniform vec3 sphereCenter9;
|
||||
uniform float sphereRadius9;
|
||||
uniform vec3 sphereCenter10;
|
||||
uniform float sphereRadius10;
|
||||
uniform vec3 sphereCenter11;
|
||||
uniform float sphereRadius11;
|
||||
uniform vec3 sphereCenter12;
|
||||
uniform float sphereRadius12;
|
||||
uniform vec3 sphereCenter13;
|
||||
uniform float sphereRadius13;
|
||||
uniform vec3 sphereCenter14;
|
||||
uniform float sphereRadius14;
|
||||
uniform vec3 sphereCenter15;
|
||||
uniform float sphereRadius15;
|
||||
uniform vec3 sphereCenter16;
|
||||
uniform float sphereRadius16;
|
||||
uniform vec3 sphereCenter17;
|
||||
uniform float sphereRadius17;
|
||||
uniform vec3 sphereCenter18;
|
||||
uniform float sphereRadius18;
|
||||
uniform vec3 sphereCenter19;
|
||||
uniform float sphereRadius19;
|
||||
uniform vec3 sphereCenter20;
|
||||
uniform float sphereRadius20;
|
||||
uniform vec3 sphereCenter21;
|
||||
uniform float sphereRadius21;
|
||||
uniform vec3 sphereCenter22;
|
||||
uniform float sphereRadius22;
|
||||
uniform vec3 sphereCenter23;
|
||||
uniform float sphereRadius23;
|
||||
uniform vec3 sphereCenter24;
|
||||
uniform float sphereRadius24;
|
||||
uniform vec3 sphereCenter25;
|
||||
uniform float sphereRadius25;
|
||||
uniform vec3 sphereCenter26;
|
||||
uniform float sphereRadius26;
|
||||
uniform vec3 sphereCenter27;
|
||||
uniform float sphereRadius27;
|
||||
uniform vec3 sphereCenter28;
|
||||
uniform float sphereRadius28;
|
||||
uniform vec3 sphereCenter29;
|
||||
uniform float sphereRadius29;
|
||||
vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeMin, vec3 cubeMax) {
|
||||
vec3 tMin = (cubeMin - origin) / ray;
|
||||
vec3 tMax = (cubeMax - origin) / ray;
|
||||
vec3 t1 = min(tMin, tMax);
|
||||
vec3 t2 = max(tMin, tMax);
|
||||
float tNear = max(max(t1.x, t1.y), t1.z);
|
||||
float tFar = min(min(t2.x, t2.y), t2.z);
|
||||
return vec2(tNear, tFar);
|
||||
}
|
||||
|
||||
vec3 normalForCube(vec3 hit, vec3 cubeMin, vec3 cubeMax) {
|
||||
if (hit.x < cubeMin.x + 0.0001) return vec3(-1.0, 0.0, 0.0);
|
||||
else if (hit.x > cubeMax.x - 0.0001) return vec3(1.0, 0.0, 0.0);
|
||||
else if (hit.y < cubeMin.y + 0.0001) return vec3(0.0, -1.0, 0.0);
|
||||
else if (hit.y > cubeMax.y - 0.0001) return vec3(0.0, 1.0, 0.0);
|
||||
else if (hit.z < cubeMin.z + 0.0001) return vec3(0.0, 0.0, -1.0);
|
||||
//else return vec3(0.0, 0.0, 1.0);
|
||||
return vec3(0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float intersectSphere(vec3 origin, vec3 ray, vec3 sphereCenter, float sphereRadius) {
|
||||
vec3 toSphere = origin - sphereCenter;
|
||||
float a = dot(ray, ray);
|
||||
float b = 2.0 * dot(toSphere, ray);
|
||||
float c = dot(toSphere, toSphere) - sphereRadius*sphereRadius;
|
||||
float discriminant = b*b - 4.0*a*c;
|
||||
if (discriminant > 0.0) {
|
||||
float t = (-b - sqrt(discriminant)) / (2.0 * a);
|
||||
if (t > 0.0) return t;
|
||||
}
|
||||
return 10000.0;
|
||||
}
|
||||
|
||||
vec3 normalForSphere(vec3 hit, vec3 sphereCenter, float sphereRadius) {
|
||||
return (hit - sphereCenter) / sphereRadius;
|
||||
}
|
||||
|
||||
float random(vec3 scale, float seed) {
|
||||
return fract(sin(dot(texCoord.xyx + seed, scale)) * 43758.5453 + seed);
|
||||
// return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
|
||||
}
|
||||
|
||||
vec3 cosineWeightedDirection(float seed, vec3 normal) {
|
||||
float u = random(vec3(12.9898, 78.233, 151.7182), seed);
|
||||
float v = random(vec3(63.7264, 10.873, 623.6736), seed);
|
||||
float r = sqrt(u);
|
||||
float angle = 6.283185307179586 * v;
|
||||
// compute basis from normal
|
||||
vec3 sdir, tdir;
|
||||
if (abs(normal.x) < 0.5) {
|
||||
sdir = cross(normal, vec3(1.0, 0.0, 0.0));
|
||||
}
|
||||
else {
|
||||
sdir = cross(normal, vec3(0.0, 1.0, 0.0));
|
||||
}
|
||||
tdir = cross(normal, sdir);
|
||||
return r*cos(angle)*sdir + r*sin(angle)*tdir + sqrt(1.0-u)*normal;
|
||||
}
|
||||
|
||||
vec3 uniformlyRandomDirection(float seed) {
|
||||
float u = random(vec3(12.9898, 78.233, 151.7182), seed);
|
||||
float v = random(vec3(63.7264, 10.873, 623.6736), seed);
|
||||
float z = 1.0 - 2.0 * u;
|
||||
float r = sqrt(1.0 - z * z);
|
||||
float angle = 6.283185307179586 * v;
|
||||
return vec3(r * cos(angle), r * sin(angle), z);
|
||||
}
|
||||
|
||||
vec3 uniformlyRandomVector(float seed) {
|
||||
return uniformlyRandomDirection(seed) * sqrt(random(vec3(36.7539, 50.3658, 306.2759), seed));
|
||||
}
|
||||
|
||||
float shadow(vec3 origin, vec3 ray) {
|
||||
|
||||
|
||||
float tSphere0 = intersectSphere(origin, ray, sphereCenter0, sphereRadius0);
|
||||
if (tSphere0 < 1.0) return 0.0;
|
||||
|
||||
float tSphere1 = intersectSphere(origin, ray, sphereCenter1, sphereRadius1);
|
||||
if (tSphere1 < 1.0) return 0.0;
|
||||
|
||||
float tSphere2 = intersectSphere(origin, ray, sphereCenter2, sphereRadius2);
|
||||
if (tSphere2 < 1.0) return 0.0;
|
||||
|
||||
float tSphere3 = intersectSphere(origin, ray, sphereCenter3, sphereRadius3);
|
||||
if (tSphere3 < 1.0) return 0.0;
|
||||
|
||||
float tSphere4 = intersectSphere(origin, ray, sphereCenter4, sphereRadius4);
|
||||
if (tSphere4 < 1.0) return 0.0;
|
||||
|
||||
float tSphere5 = intersectSphere(origin, ray, sphereCenter5, sphereRadius5);
|
||||
if (tSphere5 < 1.0) return 0.0;
|
||||
|
||||
float tSphere6 = intersectSphere(origin, ray, sphereCenter6, sphereRadius6);
|
||||
if (tSphere6 < 1.0) return 0.0;
|
||||
|
||||
float tSphere7 = intersectSphere(origin, ray, sphereCenter7, sphereRadius7);
|
||||
if (tSphere7 < 1.0) return 0.0;
|
||||
|
||||
float tSphere8 = intersectSphere(origin, ray, sphereCenter8, sphereRadius8);
|
||||
if (tSphere8 < 1.0) return 0.0;
|
||||
|
||||
float tSphere9 = intersectSphere(origin, ray, sphereCenter9, sphereRadius9);
|
||||
if (tSphere9 < 1.0) return 0.0;
|
||||
|
||||
float tSphere10 = intersectSphere(origin, ray, sphereCenter10, sphereRadius10);
|
||||
if (tSphere10 < 1.0) return 0.0;
|
||||
|
||||
float tSphere11 = intersectSphere(origin, ray, sphereCenter11, sphereRadius11);
|
||||
if (tSphere11 < 1.0) return 0.0;
|
||||
|
||||
float tSphere12 = intersectSphere(origin, ray, sphereCenter12, sphereRadius12);
|
||||
if (tSphere12 < 1.0) return 0.0;
|
||||
|
||||
float tSphere13 = intersectSphere(origin, ray, sphereCenter13, sphereRadius13);
|
||||
if (tSphere13 < 1.0) return 0.0;
|
||||
|
||||
float tSphere14 = intersectSphere(origin, ray, sphereCenter14, sphereRadius14);
|
||||
if (tSphere14 < 1.0) return 0.0;
|
||||
|
||||
float tSphere15 = intersectSphere(origin, ray, sphereCenter15, sphereRadius15);
|
||||
if (tSphere15 < 1.0) return 0.0;
|
||||
|
||||
float tSphere16 = intersectSphere(origin, ray, sphereCenter16, sphereRadius16);
|
||||
if (tSphere16 < 1.0) return 0.0;
|
||||
|
||||
float tSphere17 = intersectSphere(origin, ray, sphereCenter17, sphereRadius17);
|
||||
if (tSphere17 < 1.0) return 0.0;
|
||||
|
||||
float tSphere18 = intersectSphere(origin, ray, sphereCenter18, sphereRadius18);
|
||||
if (tSphere18 < 1.0) return 0.0;
|
||||
|
||||
float tSphere19 = intersectSphere(origin, ray, sphereCenter19, sphereRadius19);
|
||||
if (tSphere19 < 1.0) return 0.0;
|
||||
|
||||
float tSphere20 = intersectSphere(origin, ray, sphereCenter20, sphereRadius20);
|
||||
if (tSphere20 < 1.0) return 0.0;
|
||||
|
||||
float tSphere21 = intersectSphere(origin, ray, sphereCenter21, sphereRadius21);
|
||||
if (tSphere21 < 1.0) return 0.0;
|
||||
|
||||
float tSphere22 = intersectSphere(origin, ray, sphereCenter22, sphereRadius22);
|
||||
if (tSphere22 < 1.0) return 0.0;
|
||||
|
||||
float tSphere23 = intersectSphere(origin, ray, sphereCenter23, sphereRadius23);
|
||||
if (tSphere23 < 1.0) return 0.0;
|
||||
|
||||
float tSphere24 = intersectSphere(origin, ray, sphereCenter24, sphereRadius24);
|
||||
if (tSphere24 < 1.0) return 0.0;
|
||||
|
||||
float tSphere25 = intersectSphere(origin, ray, sphereCenter25, sphereRadius25);
|
||||
if (tSphere25 < 1.0) return 0.0;
|
||||
|
||||
float tSphere26 = intersectSphere(origin, ray, sphereCenter26, sphereRadius26);
|
||||
if (tSphere26 < 1.0) return 0.0;
|
||||
|
||||
float tSphere27 = intersectSphere(origin, ray, sphereCenter27, sphereRadius27);
|
||||
if (tSphere27 < 1.0) return 0.0;
|
||||
|
||||
float tSphere28 = intersectSphere(origin, ray, sphereCenter28, sphereRadius28);
|
||||
if (tSphere28 < 1.0) return 0.0;
|
||||
|
||||
float tSphere29 = intersectSphere(origin, ray, sphereCenter29, sphereRadius29);
|
||||
if (tSphere29 < 1.0) return 0.0;
|
||||
return 1.0;
|
||||
}
|
||||
vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
|
||||
vec3 colorMask = vec3(1.0);
|
||||
vec3 accumulatedColor = vec3(0.0);
|
||||
|
||||
// main raytracing loop
|
||||
for (int bounce = 0; bounce < 5; bounce++) {
|
||||
// compute the intersection with everything
|
||||
vec2 tRoom = intersectCube(origin, ray, roomCubeMin, roomCubeMax);
|
||||
|
||||
float tSphere0 = intersectSphere(origin, ray, sphereCenter0, sphereRadius0);
|
||||
float tSphere1 = intersectSphere(origin, ray, sphereCenter1, sphereRadius1);
|
||||
float tSphere2 = intersectSphere(origin, ray, sphereCenter2, sphereRadius2);
|
||||
float tSphere3 = intersectSphere(origin, ray, sphereCenter3, sphereRadius3);
|
||||
float tSphere4 = intersectSphere(origin, ray, sphereCenter4, sphereRadius4);
|
||||
float tSphere5 = intersectSphere(origin, ray, sphereCenter5, sphereRadius5);
|
||||
float tSphere6 = intersectSphere(origin, ray, sphereCenter6, sphereRadius6);
|
||||
float tSphere7 = intersectSphere(origin, ray, sphereCenter7, sphereRadius7);
|
||||
float tSphere8 = intersectSphere(origin, ray, sphereCenter8, sphereRadius8);
|
||||
float tSphere9 = intersectSphere(origin, ray, sphereCenter9, sphereRadius9);
|
||||
float tSphere10 = intersectSphere(origin, ray, sphereCenter10, sphereRadius10);
|
||||
float tSphere11 = intersectSphere(origin, ray, sphereCenter11, sphereRadius11);
|
||||
float tSphere12 = intersectSphere(origin, ray, sphereCenter12, sphereRadius12);
|
||||
float tSphere13 = intersectSphere(origin, ray, sphereCenter13, sphereRadius13);
|
||||
float tSphere14 = intersectSphere(origin, ray, sphereCenter14, sphereRadius14);
|
||||
float tSphere15 = intersectSphere(origin, ray, sphereCenter15, sphereRadius15);
|
||||
float tSphere16 = intersectSphere(origin, ray, sphereCenter16, sphereRadius16);
|
||||
float tSphere17 = intersectSphere(origin, ray, sphereCenter17, sphereRadius17);
|
||||
float tSphere18 = intersectSphere(origin, ray, sphereCenter18, sphereRadius18);
|
||||
float tSphere19 = intersectSphere(origin, ray, sphereCenter19, sphereRadius19);
|
||||
float tSphere20 = intersectSphere(origin, ray, sphereCenter20, sphereRadius20);
|
||||
float tSphere21 = intersectSphere(origin, ray, sphereCenter21, sphereRadius21);
|
||||
float tSphere22 = intersectSphere(origin, ray, sphereCenter22, sphereRadius22);
|
||||
float tSphere23 = intersectSphere(origin, ray, sphereCenter23, sphereRadius23);
|
||||
float tSphere24 = intersectSphere(origin, ray, sphereCenter24, sphereRadius24);
|
||||
float tSphere25 = intersectSphere(origin, ray, sphereCenter25, sphereRadius25);
|
||||
float tSphere26 = intersectSphere(origin, ray, sphereCenter26, sphereRadius26);
|
||||
float tSphere27 = intersectSphere(origin, ray, sphereCenter27, sphereRadius27);
|
||||
float tSphere28 = intersectSphere(origin, ray, sphereCenter28, sphereRadius28);
|
||||
float tSphere29 = intersectSphere(origin, ray, sphereCenter29, sphereRadius29);
|
||||
|
||||
// find the closest intersection
|
||||
float t = 10000.0;
|
||||
if (tRoom.x < tRoom.y) t = tRoom.y;
|
||||
|
||||
if (tSphere0 < t) t = tSphere0;
|
||||
if (tSphere1 < t) t = tSphere1;
|
||||
if (tSphere2 < t) t = tSphere2;
|
||||
if (tSphere3 < t) t = tSphere3;
|
||||
if (tSphere4 < t) t = tSphere4;
|
||||
if (tSphere5 < t) t = tSphere5;
|
||||
if (tSphere6 < t) t = tSphere6;
|
||||
if (tSphere7 < t) t = tSphere7;
|
||||
if (tSphere8 < t) t = tSphere8;
|
||||
if (tSphere9 < t) t = tSphere9;
|
||||
if (tSphere10 < t) t = tSphere10;
|
||||
if (tSphere11 < t) t = tSphere11;
|
||||
if (tSphere12 < t) t = tSphere12;
|
||||
if (tSphere13 < t) t = tSphere13;
|
||||
if (tSphere14 < t) t = tSphere14;
|
||||
if (tSphere15 < t) t = tSphere15;
|
||||
if (tSphere16 < t) t = tSphere16;
|
||||
if (tSphere17 < t) t = tSphere17;
|
||||
if (tSphere18 < t) t = tSphere18;
|
||||
if (tSphere19 < t) t = tSphere19;
|
||||
if (tSphere20 < t) t = tSphere20;
|
||||
if (tSphere21 < t) t = tSphere21;
|
||||
if (tSphere22 < t) t = tSphere22;
|
||||
if (tSphere23 < t) t = tSphere23;
|
||||
if (tSphere24 < t) t = tSphere24;
|
||||
if (tSphere25 < t) t = tSphere25;
|
||||
if (tSphere26 < t) t = tSphere26;
|
||||
if (tSphere27 < t) t = tSphere27;
|
||||
if (tSphere28 < t) t = tSphere28;
|
||||
if (tSphere29 < t) t = tSphere29;
|
||||
|
||||
// info about hit
|
||||
vec3 hit = origin + ray * t;
|
||||
vec3 surfaceColor = vec3(0.75);
|
||||
float specularHighlight = 0.0;
|
||||
vec3 normal;
|
||||
|
||||
// calculate the normal (and change wall color)
|
||||
if (t == tRoom.y) {
|
||||
normal = -normalForCube(hit, roomCubeMin, roomCubeMax);
|
||||
|
||||
if (hit.x < -0.9999) surfaceColor = vec3(0.1, 0.5, 1.0); // blue
|
||||
else if (hit.x > 0.9999) surfaceColor = vec3(1.0, 0.9, 0.1); // yellow
|
||||
|
||||
ray = cosineWeightedDirection(time + float(bounce), normal);
|
||||
}
|
||||
else if (t == 10000.0) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
int aa = 0;
|
||||
if (aa == 1) {aa = 0;} // hack to discard the first 'else' in 'else if'
|
||||
|
||||
else if (t == tSphere0) normal = normalForSphere(hit, sphereCenter0, sphereRadius0);
|
||||
else if (t == tSphere1) normal = normalForSphere(hit, sphereCenter1, sphereRadius1);
|
||||
else if (t == tSphere2) normal = normalForSphere(hit, sphereCenter2, sphereRadius2);
|
||||
else if (t == tSphere3) normal = normalForSphere(hit, sphereCenter3, sphereRadius3);
|
||||
else if (t == tSphere4) normal = normalForSphere(hit, sphereCenter4, sphereRadius4);
|
||||
else if (t == tSphere5) normal = normalForSphere(hit, sphereCenter5, sphereRadius5);
|
||||
else if (t == tSphere6) normal = normalForSphere(hit, sphereCenter6, sphereRadius6);
|
||||
else if (t == tSphere7) normal = normalForSphere(hit, sphereCenter7, sphereRadius7);
|
||||
else if (t == tSphere8) normal = normalForSphere(hit, sphereCenter8, sphereRadius8);
|
||||
else if (t == tSphere9) normal = normalForSphere(hit, sphereCenter9, sphereRadius9);
|
||||
else if (t == tSphere10) normal = normalForSphere(hit, sphereCenter10, sphereRadius10);
|
||||
else if (t == tSphere11) normal = normalForSphere(hit, sphereCenter11, sphereRadius11);
|
||||
else if (t == tSphere12) normal = normalForSphere(hit, sphereCenter12, sphereRadius12);
|
||||
else if (t == tSphere13) normal = normalForSphere(hit, sphereCenter13, sphereRadius13);
|
||||
else if (t == tSphere14) normal = normalForSphere(hit, sphereCenter14, sphereRadius14);
|
||||
else if (t == tSphere15) normal = normalForSphere(hit, sphereCenter15, sphereRadius15);
|
||||
else if (t == tSphere16) normal = normalForSphere(hit, sphereCenter16, sphereRadius16);
|
||||
else if (t == tSphere17) normal = normalForSphere(hit, sphereCenter17, sphereRadius17);
|
||||
else if (t == tSphere18) normal = normalForSphere(hit, sphereCenter18, sphereRadius18);
|
||||
else if (t == tSphere19) normal = normalForSphere(hit, sphereCenter19, sphereRadius19);
|
||||
else if (t == tSphere20) normal = normalForSphere(hit, sphereCenter20, sphereRadius20);
|
||||
else if (t == tSphere21) normal = normalForSphere(hit, sphereCenter21, sphereRadius21);
|
||||
else if (t == tSphere22) normal = normalForSphere(hit, sphereCenter22, sphereRadius22);
|
||||
else if (t == tSphere23) normal = normalForSphere(hit, sphereCenter23, sphereRadius23);
|
||||
else if (t == tSphere24) normal = normalForSphere(hit, sphereCenter24, sphereRadius24);
|
||||
else if (t == tSphere25) normal = normalForSphere(hit, sphereCenter25, sphereRadius25);
|
||||
else if (t == tSphere26) normal = normalForSphere(hit, sphereCenter26, sphereRadius26);
|
||||
else if (t == tSphere27) normal = normalForSphere(hit, sphereCenter27, sphereRadius27);
|
||||
else if (t == tSphere28) normal = normalForSphere(hit, sphereCenter28, sphereRadius28);
|
||||
else if (t == tSphere29) normal = normalForSphere(hit, sphereCenter29, sphereRadius29);
|
||||
|
||||
ray = reflect(ray, normal);
|
||||
|
||||
vec3 reflectedLight = normalize(reflect(light - hit, normal));
|
||||
specularHighlight = max(0.0, dot(reflectedLight, normalize(hit - origin)));
|
||||
specularHighlight = 2.0 * pow(specularHighlight, 20.0);
|
||||
}
|
||||
|
||||
// compute diffuse lighting contribution
|
||||
vec3 toLight = light - hit;
|
||||
float diffuse = max(0.0, dot(normalize(toLight), normal));
|
||||
|
||||
// trace a shadow ray to the light
|
||||
float shadowIntensity = shadow(hit + normal * 0.0001, toLight);
|
||||
|
||||
// do light bounce
|
||||
colorMask *= surfaceColor;
|
||||
accumulatedColor += colorMask * (0.8 * diffuse * shadowIntensity);
|
||||
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
|
||||
|
||||
// calculate next origin
|
||||
origin = hit;
|
||||
}
|
||||
|
||||
return accumulatedColor;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float time = timeSinceStart;
|
||||
vec3 col = vec3(0.0);
|
||||
const int samples = 1;
|
||||
|
||||
for (int i = 0; i < samples; i++) {
|
||||
vec3 newLight = light + uniformlyRandomVector(time - 53.0) * 0.1;
|
||||
col += calculateColor(time, eye, initialRay, newLight);
|
||||
time += 0.35;
|
||||
}
|
||||
|
||||
gl_FragColor = vec4(vec3(col / samples), 1.0);
|
||||
}
|
38
raw/pt_trace_pass/pt_trace_pass.shader.json
Executable file
38
raw/pt_trace_pass/pt_trace_pass.shader.json
Executable file
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"contexts": [
|
||||
{
|
||||
"id": "pt_trace_pass",
|
||||
"params": [
|
||||
{
|
||||
"id": "depth_write",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"id": "compare_mode",
|
||||
"value": "always"
|
||||
},
|
||||
{
|
||||
"id": "cull_mode",
|
||||
"value": "none"
|
||||
},
|
||||
{
|
||||
"id": "blend_source",
|
||||
"value": "blend_one"
|
||||
},
|
||||
{
|
||||
"id": "blend_destination",
|
||||
"value": "blend_zero"
|
||||
}
|
||||
],
|
||||
"links": [
|
||||
{
|
||||
"id": "timeSinceStart",
|
||||
"link": "_time"
|
||||
}
|
||||
],
|
||||
"texture_params": [],
|
||||
"vertex_shader": "pt_trace_pass.vert.glsl",
|
||||
"fragment_shader": "pt_trace_pass.frag.glsl"
|
||||
}
|
||||
]
|
||||
}
|
24
raw/pt_trace_pass/pt_trace_pass.vert.glsl
Normal file
24
raw/pt_trace_pass/pt_trace_pass.vert.glsl
Normal file
|
@ -0,0 +1,24 @@
|
|||
#version 450
|
||||
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
in vec2 pos;
|
||||
|
||||
uniform vec3 ray00;
|
||||
uniform vec3 ray01;
|
||||
uniform vec3 ray10;
|
||||
uniform vec3 ray11;
|
||||
|
||||
out vec3 initialRay;
|
||||
out vec2 texCoord;
|
||||
|
||||
const vec2 madd = vec2(0.5, 0.5);
|
||||
|
||||
void main() {
|
||||
// Scale vertex attribute to [0-1] range
|
||||
texCoord = pos.xy * madd + madd;
|
||||
initialRay = mix(mix(ray00, ray01, texCoord.y), mix(ray10, ray11, texCoord.y), texCoord.x);
|
||||
gl_Position = vec4(pos.xy, 0.0, 1.0);
|
||||
}
|
Loading…
Reference in a new issue