Hybrid path-tracing, blended probes.

This commit is contained in:
Lubos Lenco 2016-06-07 09:38:49 +02:00
parent 6439afb284
commit 0dbe35f27c
20 changed files with 1044 additions and 590 deletions

View file

@ -6,13 +6,12 @@ import lue.math.Vec4;
import lue.Trait;
import lue.node.Transform;
import lue.node.RootNode;
import lue.node.ModelNode;
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;
@ -28,25 +27,19 @@ class PathTracer extends Trait {
requestUpdate(update);
}
function getColorFromNode(node:ModelNode):Array<Float> {
// Hard code for now
for (c in node.materials[0].contexts[0].resource.bind_constants) {
if (c.id == "albedo_color") {
return c.vec4;
}
}
return null;
}
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",
@ -89,16 +82,15 @@ class PathTracer extends Trait {
objectLocations = [];
transformMap = new Map();
var sphereNum = 0;
var cubeNum = 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);
@ -106,12 +98,48 @@ class PathTracer extends Trait {
context.resource.bind_constants.push(
{
id: "sphereRadius" + sphereNum,
float: 0.288
float: n.transform.size.x / 2 - 0.02
}
);
var col = getColorFromNode(n);
context.resource.bind_constants.push(
{
id: "sphereColor" + sphereNum,
vec3: [col[0], col[1], col[2]]
}
);
sphereNum++;
}
else if (n.id.split(".")[0] == "Cube") {
context.resource.bind_constants.push(
{
id: "cubeCenter" + cubeNum,
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: "cubeSize" + cubeNum,
vec3: [n.transform.size.x / 2, n.transform.size.y / 2, n.transform.size.z / 2]
}
);
var col = getColorFromNode(n);
context.resource.bind_constants.push(
{
id: "cubeColor" + cubeNum,
vec3: [col[0], col[1], col[2]]
}
);
cubeNum++;
}
}
}
@ -119,9 +147,10 @@ class PathTracer extends Trait {
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 jitter = Mat4.identity();
// jitter.initTranslate(Math.random() * 2 - 1, Math.random() * 2 - 1, 0);
// jitter.multiplyScalar(1 / lue.App.w);
// jitter.multiplyScalar(1 / 400);
var mvp = Mat4.identity();
mvp.mult2(camera.V);
mvp.mult2(camera.P);
@ -131,7 +160,6 @@ class PathTracer extends Trait {
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];
@ -147,9 +175,11 @@ class PathTracer extends Trait {
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();
t.buildMatrix();
var c = context.resource.bind_constants[loc];
c.vec3[0] = t.absx();
c.vec3[1] = t.absy();
c.vec3[2] = t.absz();
}
}

View file

@ -33,6 +33,7 @@ import math
from mathutils import *
import json
import ast
import write_probes
from bpy_extras.io_utils import ExportHelper
kNodeTypeNode = 0
@ -1746,16 +1747,9 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
o = Object()
# w = worldRef[0]
w = worldRef
# o.id = worldRef[1]["structName"]
o.id = w.name
envtex = bpy.data.cameras[0].world_envtex_name.rsplit('.', 1)[0]
o.radiance = envtex + '_radiance'
o.radiance_mipmaps = bpy.data.cameras[0].world_envtex_num_mips
o.irradiance = envtex + '_irradiance'
o.brdf = 'envmap_brdf'
o.strength = bpy.data.cameras[0].world_envtex_strength
self.cb_export_world(w, o)
self.output.world_resources.append(o)
def ExportObjects(self, scene):
@ -2140,6 +2134,42 @@ class ArmoryExporter(bpy.types.Operator, ExportHelper):
else:
# TODO: gather defs from vertex data when custom shader is used
o.shader = material.custom_shader_name
def cb_export_world(self, world, o):
o.brdf = 'envmap_brdf'
o.probes = []
# Main probe
envtex = bpy.data.cameras[0].world_envtex_name.rsplit('.', 1)[0]
num_mips = bpy.data.cameras[0].world_envtex_num_mips
strength = bpy.data.cameras[0].world_envtex_strength
po = self.make_probe('world', envtex, num_mips, strength, 1.0, [0, 0, 0], [0, 0, 0])
o.probes.append(po)
# Probe cameras attached in scene
for cam in bpy.data.cameras:
if cam.is_probe:
# Generate probe straight here for now
volume_object = bpy.data.objects[cam.probe_volume]
volume = [volume_object.scale[0], volume_object.scale[1], volume_object.scale[2]]
volume_center = [volume_object.location[0], volume_object.location[1], volume_object.location[2]]
disable_hdr = cam.probe_texture.endswith('.jpg')
cam.probe_num_mips = write_probes.write_probes(cam.probe_texture, disable_hdr, cam.probe_num_mips)
base_name = cam.probe_texture.rsplit('.', 1)[0]
po = self.make_probe(cam.name, base_name, cam.probe_num_mips, cam.probe_strength, cam.probe_blending, volume, volume_center)
o.probes.append(po)
def make_probe(self, id, envtex, mipmaps, strength, blending, volume, volume_center):
po = Object()
po.id = id
po.radiance = envtex + '_radiance'
po.radiance_mipmaps = mipmaps
po.irradiance = envtex + '_irradiance'
po.strength = strength
po.blending = blending
po.volume = volume
po.volume_center = volume_center
return po
def finalize_shader(self, o, defs, pipeline_passes):
# Merge duplicates and sort

View file

@ -495,14 +495,14 @@ def buildNodeTree(node_group, shader_references, asset_references):
path = 'Assets/generated/pipelines/'
node_group_name = node_group.name.replace('.', '_')
res.id = node_group_name
res.render_targets, res.depth_buffers = get_render_targets(node_group)
res.stages = []
rn = getRootNode(node_group)
if rn == None:
return
res.id = node_group_name
res.render_targets, res.depth_buffers = get_render_targets(rn, node_group)
res.stages = []
# Used to merge bind target nodes into one stage
last_bind_target = None
@ -602,10 +602,11 @@ def make_draw_material_quad(stage, node_group, node, shader_references, asset_re
material_context = node.inputs[context_index].default_value
stage.params.append(material_context)
# Include resource and shaders
shader_context = node.inputs[context_index].default_value
scon = shader_context.split('/')
dir_name = scon[0]
# Append world defs
res_name = scon[1]
dir_name = scon[2]
# No world defs for material passes
res_name = scon[2]
asset_references.append('compiled/ShaderResources/' + dir_name + '/' + res_name + '.json')
shader_references.append('compiled/Shaders/' + dir_name + '/' + res_name)
@ -758,6 +759,57 @@ def getRootNode(node_group):
if n.bl_idname == 'BeginNodeType':
return findNodeByLinkFrom(node_group, n, n.outputs[0])
def get_render_targets(root_node, node_group):
render_targets = []
depth_buffers = []
traverse_for_rt(root_node, node_group, render_targets, depth_buffers)
return render_targets, depth_buffers
def traverse_for_rt(node, node_group, render_targets, depth_buffers):
# Collect render targets
if node.bl_idname == 'SetTargetNodeType':
if node.inputs[1].is_linked:
tnode = findNodeByLink(node_group, node, node.inputs[1])
parse_render_target(tnode, node_group, render_targets, depth_buffers)
# Next stage
if node.outputs[0].is_linked:
stagenode = findNodeByLinkFrom(node_group, node, node.outputs[0])
traverse_for_rt(stagenode, node_group, render_targets, depth_buffers)
def parse_render_target(node, node_group, render_targets, depth_buffers):
if node.bl_idname == 'TargetNodeType':
# Target already exists
id = node.inputs[0].default_value
for t in render_targets:
if t.id == id:
return
depth_buffer_id = None
if node.inputs[3].is_linked:
# Find depth buffer
depth_node = findNodeByLink(node_group, node, node.inputs[3])
depth_buffer_id = depth_node.inputs[0].default_value
# Append depth buffer
found = False
for db in depth_buffers:
if db.id == depth_buffer_id:
found = True
break
if found == False:
db = Object()
db.id = depth_buffer_id
db.stencil_buffer = depth_node.inputs[1].default_value
depth_buffers.append(db)
# Append target
target = make_render_target(node, depth_buffer_id=depth_buffer_id)
render_targets.append(target)
elif node.bl_idname == 'GBufferNodeType':
for i in range(0, 5):
if node.inputs[i].is_linked:
n = findNodeByLink(node_group, node, node.inputs[i])
parse_render_target(n, node_group, render_targets, depth_buffers)
def make_render_target(n, depth_buffer_id=None):
target = Object()
target.id = n.inputs[0].default_value
@ -768,28 +820,4 @@ def make_render_target(n, depth_buffer_id=None):
if depth_buffer_id != None:
target.depth_buffer = depth_buffer_id
return target
def get_render_targets(node_group):
render_targets = []
depth_buffers = []
for n in node_group.nodes:
if n.bl_idname == 'TargetNodeType':
depth_buffer_id = None
if n.inputs[3].is_linked:
depth_node = findNodeByLink(node_group, n, n.inputs[3])
depth_buffer_id = depth_node.inputs[0].default_value
# Append depth buffer
found = False
for db in depth_buffers:
if db.id == depth_buffer_id:
found = True
break
if found == False:
db = Object()
db.id = depth_buffer_id
db.stencil_buffer = depth_node.inputs[1].default_value
depth_buffers.append(db)
# Append target
target = make_render_target(n, depth_buffer_id=depth_buffer_id)
render_targets.append(target)
return render_targets, depth_buffers

View file

@ -2,9 +2,8 @@ import bpy
from bpy.types import NodeTree, Node, NodeSocket
from bpy.props import *
import os
import sys
import json
import subprocess
import write_probes
def register():
pass
@ -62,15 +61,18 @@ def buildNodeTree(world_name, node_group, shader_references, asset_references):
for node in node_group.nodes:
# Env map included
if node.type == 'TEX_ENVIRONMENT': # Just look for env texture for now
image_name = node.image.name
image_name = node.image.name # With extension
texture.name = image_name.rsplit('.', 1)[0] # Remove extension
# Add resources to khafie
asset_references.append('compiled/ShaderResources/env_map/env_map.json')
shader_references.append('compiled/Shaders/env_map/env_map')
# Generate prefiltered envmaps
bpy.data.cameras[0].world_envtex_name = texture.name
disable_hdr = image_name.endswith('.jpg')
generate_envmaps(image_name, disable_hdr)
mip_count = bpy.data.cameras[0].world_envtex_num_mips
mip_count = write_probes.write_probes(image_name, disable_hdr, mip_count)
bpy.data.cameras[0].world_envtex_num_mips = mip_count
# Append envtex define
bpy.data.worlds[0].world_defs += '_EnvTex'
@ -83,152 +85,13 @@ def buildNodeTree(world_name, node_group, shader_references, asset_references):
bpy.data.cameras[0].world_envtex_strength = node.inputs[1].default_value
if node.type == 'TEX_SKY':
bpy.data.worlds[0].world_defs += '_EnvSky'
# Enable probes
num_probes = 0
for cam in bpy.data.cameras:
if cam.is_probe:
num_probes += 1
bpy.data.worlds[0].world_defs += '_Probe' + str(num_probes)
with open(path + material_name + '.json', 'w') as f:
f.write(output.to_JSON())
def generate_envmaps(image_name, disable_hdr):
if not os.path.exists('Assets/generated/envmaps'):
os.makedirs('Assets/generated/envmaps')
# Get paths
# haxelib_path = "haxelib"
# if platform.system() == 'Darwin':
# haxelib_path = "/usr/local/bin/haxelib"
# output = subprocess.check_output([haxelib_path + " path cyclesgame"], shell=True)
# output = str(output).split("\\n")[0].split("'")[1]
# cmft_path = output[:-8] + "tools/cmft/"
cmft_path = 'Libraries/cyclesgame/tools/cmft/'
kraffiti_path = 'Kha/Kore/Tools/kraffiti/'
generated_files = []
output_gama_numerator = '1.0' if disable_hdr else '2.2'
base_name = image_name.rsplit('.', 1)[0]
input_file = 'Assets/textures/' + image_name
# Get input size
output = subprocess.check_output([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + input_file + \
' donothing'], shell=True)
# #%ix%i
image_w = str(output).split("'")[1]
image_w = image_w[1:]
image_w = image_w.split('x')[0]
image_w = int(image_w)
image_h = image_w / 2
# 4096 = 256 face - 6 mips - 1024 latlong
# 2048 = 128 face - 5 mips - 512 latlong
# 1024 = 64 face - 4 mips
# 512 = 32 face - 3 mips
# 256 = 16 face - 2 mips
# 128 = 8 face - 1 mip
mip_count = 1
num = 128
while num < image_w:
num *= 2
mip_count += 1
face_size = image_w / 16
src_face_size = str(face_size)
dst_face_size = str(face_size)
# Generate irradiance
gama_options = ''
if disable_hdr:
gama_options = \
' --inputGammaNumerator 2.2' + \
' --inputGammaDenominator 1.0' + \
' --outputGammaNumerator 1.0' + \
' --outputGammaDenominator ' + output_gama_numerator
output_file = 'Assets/generated/envmaps/' + base_name + '_irradiance'
subprocess.call([ \
cmft_path + 'cmft-osx' + \
' --input ' + input_file + \
' --filter irradiance' + \
' --dstFaceSize ' + dst_face_size + \
gama_options + \
' --outputNum 1' + \
' --output0 ' + output_file + \
' --output0params hdr,rgbe,latlong'], shell=True)
generated_files.append(output_file)
# Generate radiance
output_file = 'Assets/generated/envmaps/' + base_name + '_radiance'
outformat = 'jpg' if disable_hdr else 'hdr'
output = subprocess.check_output([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + input_file + \
' to=' + output_file + '.' + outformat + \
' format=' + outformat + \
' scale=0.5'], shell=True)
subprocess.call([ \
cmft_path + 'cmft-osx' + \
' --input ' + input_file + \
' --filter radiance' + \
' --dstFaceSize ' + dst_face_size + \
' --srcFaceSize ' + src_face_size + \
' --excludeBase false' + \
' --mipCount ' + str(mip_count) + \
' --glossScale 7' + \
' --glossBias 3' + \
' --lightingModel blinnbrdf' + \
' --edgeFixup none' + \
' --numCpuProcessingThreads 4' + \
' --useOpenCL true' + \
' --clVendor anyGpuVendor' + \
' --deviceType gpu' + \
' --deviceIndex 0' + \
' --generateMipChain false' + \
' --inputGammaNumerator 2.2' + \
' --inputGammaDenominator 1.0' + \
' --outputGammaNumerator 1.0' + \
' --outputGammaDenominator ' + output_gama_numerator + \
' --outputNum 1' + \
' --output0 ' + output_file + \
' --output0params hdr,rgbe,latlong'], shell=True)
# Remove size extensions in file name
mip_w = int(face_size * 4)
mip_h = int(face_size * 2)
mip_base = output_file + '_'
mip_num = 0
while mip_w >= 32:
mip_name = mip_base + str(mip_num)
os.rename(
mip_name + '_' + str(mip_w) + 'x' + str(mip_h) + '.hdr',
mip_name + '.hdr')
mip_w = int(mip_w / 2)
mip_h = int(mip_h / 2)
mip_num += 1
# Append mips
for i in range(0, mip_count):
generated_files.append(output_file + '_' + str(i))
# Convert to jpgs
if disable_hdr is True:
for f in generated_files:
subprocess.call([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + f + '.hdr' + \
' to=' + f + '.jpg' + \
' format=jpg'], shell=True)
os.remove(f + '.hdr')
# Scale from (32x16 to 1x1>
for i in range (0, 5):
last = generated_files[-1]
out = output_file + '_' + str(mip_count + i)
subprocess.call([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + last + '.' + outformat + \
' to=' + out + '.' + outformat + \
' scale=0.5' + \
' format=' + outformat], shell=True)
generated_files.append(out)
mip_count += 5
bpy.data.cameras[0].world_envtex_num_mips = mip_count

View file

@ -4,8 +4,7 @@
import bpy
import os
bounces = '5'
bounces = '2'
epsilon = '0.0001'
infinity = '10000.0'
lightSize = 0.1
@ -17,12 +16,11 @@ 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
material = MATERIAL_DIFFUSE
# YELLOW_BLUE_CORNELL_BOX = 0
# RED_GREEN_CORNELL_BOX = 1
# environment = YELLOW_BLUE_CORNELL_BOX
def concat(objects, func):
text = ''
@ -30,7 +28,6 @@ def concat(objects, func):
text += func(objects[i])
return text
tracerFragmentSourceHeader = """
#version 450
#ifdef GL_ES
@ -43,15 +40,22 @@ uniform vec3 eye;
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);
//vec3 roomCubeMin = vec3(0.0, 0.0, 0.0);
//vec3 roomCubeMax = vec3(1.0, 1.0, 1.0);
vec3 origin;
vec3 ray;
vec3 colorMask = vec3(1.0);
vec3 accumulatedColor = vec3(0.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) {
vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeCenter, vec3 cubeSize) {
vec3 cubeMin = cubeCenter - cubeSize;
vec3 cubeMax = cubeCenter + cubeSize;
vec3 tMin = (cubeMin - origin) / ray;
vec3 tMax = (cubeMax - origin) / ray;
vec3 t1 = min(tMin, tMax);
@ -66,14 +70,16 @@ vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeMin, vec3 cubeMax) {
# 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) {
vec3 normalForCube(vec3 hit, vec3 cubeCenter, vec3 cubeSize) {
vec3 cubeMin = cubeCenter - cubeSize;
vec3 cubeMax = cubeCenter + cubeSize;
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);
return vec3(0.0, 0.0, 1.0);
}
"""
@ -117,7 +123,7 @@ vec3 cosineWeightedDirection(float seed, vec3 normal) {
if (abs(normal.x) < 0.5) {
sdir = cross(normal, vec3(1.0, 0.0, 0.0));
}
else {
else {
sdir = cross(normal, vec3(0.0, 1.0, 0.0));
}
tdir = cross(normal, sdir);
@ -129,8 +135,11 @@ vec3 cosineWeightedDirection(float seed, vec3 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);
// return fract(sin(dot(texCoord.xyx + seed, scale)) * 43758.5453 + seed);
float d = 43758.5453;
float dt = dot(texCoord.xyx + seed,scale);
float sn = mod(dt,3.1415926);
return fract(sin(sn) * d);
}
"""
@ -182,14 +191,14 @@ newGlossyRay = """
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"""
# yellowBlueCornellBox = """
# if (hit.x < -0.9999) surfaceColor = vec3(0.1, 0.1, 0.7); // blue
# else if (hit.x > 0.9999) surfaceColor = vec3(0.7, 0.1, 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"""
# 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):
@ -215,22 +224,14 @@ def _getMinimumIntersectCode(o):
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);
def makeDoBounce(objects):
return """
int doBounce(float time, vec3 light, int bounce) {
// compute the intersection with everything
""" + concat(objects, _getIntersectCode) + """
// find the closest intersection
float t = """ + infinity + """;
if (tRoom.x < tRoom.y) t = tRoom.y;
""" + concat(objects, _getMinimumIntersectCode) + """
// info about hit
@ -239,17 +240,12 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
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;
if (t == """ + infinity + """) {
//break;
return 0;
}
else {
int aa = 0;
int aa = 0;
if (aa == 1) {aa = 0;} // hack to discard the first 'else' in 'else if'
""" + concat(objects, _getNormalCalculationCode) + """
""" + [newDiffuseRay, newReflectiveRay, newGlossyRay][material] + """
@ -257,39 +253,75 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
// 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);
//float diffuse = max(0.0, dot(normalize(toLight), normal));
float diffuse = max(0.0, dot(normalize(toLight), normal)) / dot(toLight,toLight);
// do light bounce
colorMask *= surfaceColor;
accumulatedColor += colorMask * (""" + str(lightVal) + """ * diffuse * shadowIntensity);
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
//if (bounce > 0) {
// trace a shadow ray to the light
float shadowIntensity = shadow(hit + normal * """ + epsilon + """, toLight);
accumulatedColor += colorMask * (""" + str(lightVal) + """ * diffuse * shadowIntensity);
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
//}
// calculate next origin
origin = hit;
}
return 0;
}
"""
def makeCalculateColor(objects):
return """
vec3 calculateColor(float time, vec3 _origin, vec3 _ray, vec3 light) {
//vec3 colorMask = vec3(1.0);
//vec3 accumulatedColor = vec3(0.0);
origin = _origin;
ray = _ray;
// main raytracing loop
//for (int bounce = 0; bounce < """ + bounces + """; bounce++) {
int a;
a = doBounce(time, light, 0);
a = doBounce(time, light, 1);
a = doBounce(time, light, 2);
//}
return accumulatedColor;
}
"""
def makeDoSamples(num_samples):
s = ''
for i in range(0, num_samples):
s += """newLight = light + uniformlyRandomVector(time - 53.0) * """ + str(lightSize) + """;
"""
s += """col += calculateColor(time, eye, initialRay, newLight);
"""
s += """time += 0.35;
"""
return s
def makeMain():
return """
void main() {
float time = timeSinceStart;
float time = 0.0;//timeSinceStart;
//timeSinceStart % 46735.275 ) / 1000;
vec3 col = vec3(0.0);
const int samples = 1;
vec3 newLight;
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;
}
//for (int i = 0; i < samples; i++) {
""" + \
makeDoSamples(1) + \
"""
//}
gl_FragColor = vec4(vec3(col / samples), 1.0);
gl_FragColor.rgb = pow(gl_FragColor.rgb * 0.7, vec3(1.0 / 2.2));
}
"""
@ -310,22 +342,26 @@ def makeTracerFragmentSource(objects):
uniformlyRandomDirectionSource + \
uniformlyRandomVectorSource + \
makeShadow(objects) + \
makeDoBounce(objects) + \
makeCalculateColor(objects) + \
makeMain()
class Sphere:
def __init__(self, center, radius, id):
def __init__(self, center, radius, color, id):
self.center = center;
self.radius = radius;
self.color = color;
self.centerStr = 'sphereCenter' + str(id);
self.radiusStr = 'sphereRadius' + str(id);
self.colorStr = 'sphereColor' + str(id);
self.intersectStr = 'tSphere' + str(id);
def getGlobalCode(self):
return """
uniform vec3 """ + self.centerStr + """;
uniform float """ + self.radiusStr + """;"""
uniform float """ + self.radiusStr + """;
uniform vec3 """ + self.colorStr + """;"""
def getIntersectCode(self):
return """
@ -342,25 +378,28 @@ uniform float """ + self.radiusStr + """;"""
def getNormalCalculationCode(self):
return """
else if (t == """ + self.intersectStr + """) normal = normalForSphere(hit, """ + self.centerStr + """, """ + self.radiusStr + """);"""
else if (t == """ + self.intersectStr + """) { normal = normalForSphere(hit, """ + self.centerStr + """, """ + self.radiusStr + """); surfaceColor = """ + self.colorStr + """; }"""
class Cube:
def __init__(self, minCorner, maxCorner, id):
self.minCorner = minCorner;
self.maxCorner = maxCorner;
self.minStr = 'cubeMin' + str(id);
self.maxStr = 'cubeMax' + str(id);
def __init__(self, center, size, color, id):
self.center = center;
self.size = size;
self.color = color;
self.centerStr = 'cubeCenter' + str(id);
self.sizeStr = 'cubeSize' + str(id);
self.colorStr = 'cubeColor' + str(id);
self.intersectStr = 'tCube' + str(id);
def getGlobalCode(self):
return """
uniform vec3 """ + self.minStr + """;
uniform vec3 """ + self.maxStr + """;"""
uniform vec3 """ + self.centerStr + """;
uniform vec3 """ + self.sizeStr + """;
uniform vec3 """ + self.colorStr + """;"""
def getIntersectCode(self):
return """
vec2 """ + self.intersectStr + """ = intersectCube(origin, ray, """ + self.minStr + """, """ + self.maxStr + """);"""
vec2 """ + self.intersectStr + """ = intersectCube(origin, ray, """ + self.centerStr + """, """ + self.sizeStr + """);"""
def getShadowTestCode(self):
return """
@ -375,7 +414,8 @@ uniform vec3 """ + self.maxStr + """;"""
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 + """);"""
else if (t == """ + self.intersectStr + """.x) { if (""" + self.intersectStr + """.x < """ + self.intersectStr + """.y) normal = normalForCube(hit, """ + self.centerStr + """, """ + self.sizeStr + """); surfaceColor = """ + self.colorStr + """; }"""
#else if (t == """ + self.intersectStr + """.x && """ + self.intersectStr + """.x < """ + self.intersectStr + """.y) normal = normalForCube(hit, """ + self.centerStr + """, """ + self.sizeStr + """);"""
class Light:
@ -399,16 +439,20 @@ class Light:
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
nextSphereId = 0
nextCubeId = 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, [0.8, 0.8, 0.8], nextSphereId))
nextSphereId += 1
elif o.name.split('.', 1)[0] == 'Cube':
objects.append(Cube([0, 0, 0], [0, 0, 0], [0.8, 0.8, 0.8], nextCubeId))
nextCubeId += 1
return objects
objects = initObjects()

View file

@ -29,6 +29,12 @@ def initProperties():
bpy.types.Camera.geometry_context = bpy.props.StringProperty(name="Geometry", default="deferred")
bpy.types.Camera.shadows_context = bpy.props.StringProperty(name="Shadows", default="shadowmap")
bpy.types.Camera.translucent_context = bpy.props.StringProperty(name="Translucent", default="translucent")
bpy.types.Camera.is_probe = bpy.props.BoolProperty(name="Probe", default=False)
bpy.types.Camera.probe_texture = bpy.props.StringProperty(name="Texture", default="")
bpy.types.Camera.probe_num_mips = bpy.props.IntProperty(name="Number of mips", default=0)
bpy.types.Camera.probe_volume = bpy.props.StringProperty(name="Volume", default="")
bpy.types.Camera.probe_strength = bpy.props.FloatProperty(name="Strength", default=1.0)
bpy.types.Camera.probe_blending = bpy.props.FloatProperty(name="Blending", default=0.0)
# TODO: move to world
bpy.types.Camera.world_envtex_name = bpy.props.StringProperty(name="Environment Texture", default='')
bpy.types.Camera.world_envtex_num_mips = bpy.props.IntProperty(name="Number of mips", default=0)
@ -74,6 +80,13 @@ class DataPropsPanel(bpy.types.Panel):
obj = bpy.context.object
if obj.type == 'CAMERA':
layout.prop(obj.data, 'is_probe')
if obj.data.is_probe == True:
layout.prop(obj.data, 'probe_texture')
layout.prop_search(obj.data, "probe_volume", bpy.data, "objects")
layout.prop(obj.data, 'probe_strength')
layout.prop(obj.data, 'probe_blending')
layout.prop(obj.data, 'frustum_culling')
layout.prop(obj.data, 'sort_front_to_back')
layout.prop_search(obj.data, "pipeline_path", bpy.data, "node_groups")

158
blender/write_probes.py Normal file
View file

@ -0,0 +1,158 @@
import bpy
import os
import sys
import subprocess
# Generate probes from environment map
def write_probes(image_name, disable_hdr, cached_num_mips):
if not os.path.exists('Assets/generated/envmaps'):
os.makedirs('Assets/generated/envmaps')
name_split = image_name.rsplit('.', 1)
base_name = name_split[0]
ext_name = name_split[1]
# Assume irradiance has to exist for now
if os.path.exists('Assets/generated/envmaps/' + base_name + '_irradiance.' + ext_name):
return cached_num_mips
# Get paths
# haxelib_path = "haxelib"
# if platform.system() == 'Darwin':
# haxelib_path = "/usr/local/bin/haxelib"
# output = subprocess.check_output([haxelib_path + " path cyclesgame"], shell=True)
# output = str(output).split("\\n")[0].split("'")[1]
# cmft_path = output[:-8] + "tools/cmft/"
cmft_path = 'Libraries/cyclesgame/tools/cmft/'
kraffiti_path = 'Kha/Kore/Tools/kraffiti/'
generated_files = []
output_gama_numerator = '1.0' if disable_hdr else '2.2'
input_file = 'Assets/textures/' + image_name
# Get input size
output = subprocess.check_output([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + input_file + \
' donothing'], shell=True)
# #%ix%i
image_w = str(output).split("'")[1]
image_w = image_w[1:]
image_w = image_w.split('x')[0]
image_w = int(image_w)
image_h = image_w / 2
# 4096 = 256 face - 6 mips - 1024 latlong
# 2048 = 128 face - 5 mips - 512 latlong
# 1024 = 64 face - 4 mips
# 512 = 32 face - 3 mips
# 256 = 16 face - 2 mips
# 128 = 8 face - 1 mip
mip_count = 1
num = 128
while num < image_w:
num *= 2
mip_count += 1
face_size = image_w / 16
src_face_size = str(face_size)
dst_face_size = str(face_size)
# Generate irradiance
gama_options = ''
if disable_hdr:
gama_options = \
' --inputGammaNumerator 2.2' + \
' --inputGammaDenominator 1.0' + \
' --outputGammaNumerator 1.0' + \
' --outputGammaDenominator ' + output_gama_numerator
output_file = 'Assets/generated/envmaps/' + base_name + '_irradiance'
subprocess.call([ \
cmft_path + 'cmft-osx' + \
' --input ' + input_file + \
' --filter irradiance' + \
' --dstFaceSize ' + dst_face_size + \
gama_options + \
' --outputNum 1' + \
' --output0 ' + output_file + \
' --output0params hdr,rgbe,latlong'], shell=True)
generated_files.append(output_file)
# Generate radiance
output_file = 'Assets/generated/envmaps/' + base_name + '_radiance'
outformat = 'jpg' if disable_hdr else 'hdr'
output = subprocess.check_output([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + input_file + \
' to=' + output_file + '.' + outformat + \
' format=' + outformat + \
' scale=0.5'], shell=True)
subprocess.call([ \
cmft_path + 'cmft-osx' + \
' --input ' + input_file + \
' --filter radiance' + \
' --dstFaceSize ' + dst_face_size + \
' --srcFaceSize ' + src_face_size + \
' --excludeBase false' + \
' --mipCount ' + str(mip_count) + \
' --glossScale 7' + \
' --glossBias 3' + \
' --lightingModel blinnbrdf' + \
' --edgeFixup none' + \
' --numCpuProcessingThreads 4' + \
' --useOpenCL true' + \
' --clVendor anyGpuVendor' + \
' --deviceType gpu' + \
' --deviceIndex 0' + \
' --generateMipChain false' + \
' --inputGammaNumerator 2.2' + \
' --inputGammaDenominator 1.0' + \
' --outputGammaNumerator 1.0' + \
' --outputGammaDenominator ' + output_gama_numerator + \
' --outputNum 1' + \
' --output0 ' + output_file + \
' --output0params hdr,rgbe,latlong'], shell=True)
# Remove size extensions in file name
mip_w = int(face_size * 4)
mip_h = int(face_size * 2)
mip_base = output_file + '_'
mip_num = 0
while mip_w >= 32:
mip_name = mip_base + str(mip_num)
os.rename(
mip_name + '_' + str(mip_w) + 'x' + str(mip_h) + '.hdr',
mip_name + '.hdr')
mip_w = int(mip_w / 2)
mip_h = int(mip_h / 2)
mip_num += 1
# Append mips
for i in range(0, mip_count):
generated_files.append(output_file + '_' + str(i))
# Convert to jpgs
if disable_hdr is True:
for f in generated_files:
subprocess.call([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + f + '.hdr' + \
' to=' + f + '.jpg' + \
' format=jpg'], shell=True)
os.remove(f + '.hdr')
# Scale from (32x16 to 1x1>
for i in range (0, 5):
last = generated_files[-1]
out = output_file + '_' + str(mip_count + i)
subprocess.call([ \
kraffiti_path + 'kraffiti-osx' + \
' from=' + last + '.' + outformat + \
' to=' + out + '.' + outformat + \
' scale=0.5' + \
' format=' + outformat], shell=True)
generated_files.append(out)
mip_count += 5
return mip_count

View file

@ -0,0 +1,90 @@
#version 450
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D tex;
uniform sampler2D gbuffer0;
uniform vec2 dir;
in vec2 texCoord;
const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
const float discardThreshold = 0.95;
vec3 result = vec3(0.0);
vec2 octahedronWrap(vec2 v) {
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
}
vec3 getNor(vec2 enc) {
vec3 n;
n.z = 1.0 - abs(enc.x) - abs(enc.y);
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
n = normalize(n);
return n;
}
float doBlur(float blurWeight, int pos, vec3 nor) {
vec2 texstep = dir / vec2(800, 600);
vec2 texstep2 = dir / vec2(800, 600);
vec3 nor2 = getNor(texture(gbuffer0, texCoord + pos * texstep2).rg);
float influenceFactor = step(discardThreshold, dot(nor2, nor));
vec3 col = texture(tex, texCoord + pos * texstep).rgb;
result += col * blurWeight * influenceFactor;
float weight = blurWeight * influenceFactor;
nor2 = getNor(texture(gbuffer0, texCoord - pos * texstep2).rg);
influenceFactor = step(discardThreshold, dot(nor2, nor));
col = texture(tex, texCoord - pos * texstep).rgb;
result += col * blurWeight * influenceFactor;
weight += blurWeight * influenceFactor;
return weight;
}
void main() {
vec2 texstep = dir / vec2(800, 600);
vec2 texstep2 = dir / vec2(800, 600);
vec3 nor = getNor(texture(gbuffer0, texCoord).rg);
float weight = 0.0;
// for (int i = 0; i < 9; i++) {
// float blurWeight = blurWeights[0];
const float radius = 10.0;
const float blurWeight = 1.0 / radius;
vec3 col = texture(tex, texCoord).rgb;
result += col * blurWeights[0];
weight += blurWeight;
weight += doBlur(blurWeights[1], 1, nor);
weight += doBlur(blurWeights[2], 2, nor);
weight += doBlur(blurWeights[3], 3, nor);
weight += doBlur(blurWeights[4], 4, nor);
weight += doBlur(blurWeights[5], 5, nor);
weight += doBlur(blurWeights[6], 6, nor);
weight += doBlur(blurWeights[7], 7, nor);
weight += doBlur(blurWeights[8], 8, nor);
weight += doBlur(blurWeights[9], 9, nor);
// weight += doBlur(blurWeight, 1, nor);
// weight += doBlur(blurWeight, 2, nor);
// weight += doBlur(blurWeight, 3, nor);
// weight += doBlur(blurWeight, 4, nor);
// weight += doBlur(blurWeight, 5, nor);
// weight += doBlur(blurWeight, 6, nor);
// weight += doBlur(blurWeight, 7, nor);
// weight += doBlur(blurWeight, 8, nor);
// weight += doBlur(blurWeight, 9, nor);
// weight += doBlur(blurWeight, 10, nor);
// }
result /= weight;
gl_FragColor = vec4(result.rgb, 1.0);
}

View file

@ -0,0 +1,60 @@
{
"contexts": [
{
"id": "blur_edge_pass_x",
"params": [
{
"id": "depth_write",
"value": "true"
},
{
"id": "compare_mode",
"value": "always"
},
{
"id": "cull_mode",
"value": "none"
}
],
"links": [
{
"id": "dir",
"link": "_vec2x"
}
],
"texture_params": [],
"vertex_shader": "blur_edge_pass.vert.glsl",
"fragment_shader": "blur_edge_pass.frag.glsl"
},
{
"id": "blur_edge_pass_y",
"params": [
{
"id": "depth_write",
"value": "true"
},
{
"id": "compare_mode",
"value": "always"
},
{
"id": "cull_mode",
"value": "none"
},
{
"id": "dir",
"link": "_vec2y"
}
],
"links": [
{
"id": "dir",
"link": "_vec2y"
}
],
"texture_params": [],
"vertex_shader": "blur_edge_pass.vert.glsl",
"fragment_shader": "blur_edge_pass.frag.glsl"
}
]
}

View 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);
}

View file

@ -9,21 +9,40 @@ uniform vec2 dir;
in vec2 texCoord;
const vec2 screenSize = vec2(1920, 1080);
const vec2 screenSize = vec2(800, 600);
void main() {
vec2 step = dir / screenSize;
float result = texture(tex, texCoord + (step * 4.0)).r;
result += texture(tex, texCoord + (step * 3.0)).r;
result += texture(tex, texCoord + (step * 2.0)).r;
result += texture(tex, texCoord + step).r;
result += texture(tex, texCoord).r;
result += texture(tex, texCoord - step).r;
result += texture(tex, texCoord - (step * 2.0)).r;
result += texture(tex, texCoord - (step * 3.0)).r;
result += texture(tex, texCoord - (step * 4.0)).r;
result /= 9.0;
vec3 result = texture(tex, texCoord + (step * 4.0)).rgb;
result += texture(tex, texCoord + (step * 3.0)).rgb;
result += texture(tex, texCoord + (step * 2.0)).rgb;
result += texture(tex, texCoord + step).rgb;
result += texture(tex, texCoord).rgb;
result += texture(tex, texCoord - step).rgb;
result += texture(tex, texCoord - (step * 2.0)).rgb;
result += texture(tex, texCoord - (step * 3.0)).rgb;
result += texture(tex, texCoord - (step * 4.0)).rgb;
result /= vec3(9.0);
// vec3 result = texture(tex, texCoord + (step * 8.0)).rgb;
// result += texture(tex, texCoord + (step * 7.0)).rgb;
// result += texture(tex, texCoord + (step * 6.0)).rgb;
// result += texture(tex, texCoord + (step * 5.0)).rgb;
// result += texture(tex, texCoord + (step * 4.0)).rgb;
// result += texture(tex, texCoord + (step * 3.0)).rgb;
// result += texture(tex, texCoord + (step * 2.0)).rgb;
// result += texture(tex, texCoord + step).rgb;
// result += texture(tex, texCoord).rgb;
// result += texture(tex, texCoord - step).rgb;
// result += texture(tex, texCoord - (step * 2.0)).rgb;
// result += texture(tex, texCoord - (step * 3.0)).rgb;
// result += texture(tex, texCoord - (step * 4.0)).rgb;
// result += texture(tex, texCoord - (step * 5.0)).rgb;
// result += texture(tex, texCoord - (step * 6.0)).rgb;
// result += texture(tex, texCoord - (step * 7.0)).rgb;
// result += texture(tex, texCoord - (step * 8.0)).rgb;
// result /= vec3(17.0);
gl_FragColor.rgb = vec3(result);
}

View file

@ -1,66 +0,0 @@
#version 450
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D tex;
// uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform vec2 dir;
in vec2 texCoord;
void main() {
vec2 pixelStep = dir / vec2(800, 600);
vec3 blurredResult = vec3( 0.0, 0.0, 0.0 );
float depth = texture(gbuffer0, texCoord).a;
float weight = 0.0;
// for (float i = -3.0; i <= 3.0; i += 1.0) {
// float pixelDepth = texture(gbuffer0, texCoord + i * pixelStep).a;
// float pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
// weight += pixelWeight;
// blurredResult += texture(tex, texCoord + i * pixelStep).rgb * pixelWeight;
float pixelDepth = texture(gbuffer0, texCoord + pixelStep * -3).a;
float pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * -3).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * -2).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * -2).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * -1).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * -1).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * 0).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * 0).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * 1).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * 1).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * 2).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * 2).rgb * pixelWeight;
pixelDepth = texture(gbuffer0, texCoord + pixelStep * 3).a;
pixelWeight = max(0.0, 1.0 - step(0.2, abs(depth - pixelDepth)));
weight += pixelWeight;
blurredResult += texture(tex, texCoord + pixelStep * 3).rgb * pixelWeight;
// }
blurredResult /= weight;
gl_FragColor = vec4(vec3(blurredResult), 1.0);
}

View file

@ -348,5 +348,9 @@ void main() {
// col.rgb = vec3(clamp(dot(col.rgb, col.rgb), 0.0, 1.0));
// col.rgb = vec3((col.r * 0.3 + col.g * 0.59 + col.b * 0.11) / 3.0) * 2.5;
// Letter box
// const float letterBoxSize = 0.1;
// col.rgb *= 1.0 - step(0.5 - letterBoxSize, abs(0.5 - texCoord.y));
gl_FragColor = col;
}

View file

@ -29,6 +29,12 @@ uniform float metalness;
#endif
uniform float mask;
#ifdef _Probe1
uniform int probeID;
uniform vec3 probeVolumeCenter;
uniform vec3 probeVolumeSize;
#endif
in vec4 mvpposition;
#ifdef _AMTex
in vec2 texCoord;
@ -41,6 +47,10 @@ in mat3 TBN;
in vec3 normal;
#endif
#ifdef _Probe1
in vec4 mpos;
#endif
float packFloat(float f1, float f2) {
int index = int(f1 * 1000);
float alpha = f2 == 0.0 ? f2 : (f2 - 0.0001);
@ -52,6 +62,13 @@ vec2 octahedronWrap(vec2 v) {
return (1.0 - abs(v.yx)) * (vec2(v.x >= 0.0 ? 1.0 : -1.0, v.y >= 0.0 ? 1.0 : -1.0));
}
#ifdef _Probe1
float distanceBox(vec3 point, vec3 center, vec3 halfExtents) {
vec3 d = abs(point - center) - halfExtents;
return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, 0.0));
}
#endif
void main() {
#ifdef _NMTex
@ -90,6 +107,16 @@ void main() {
n /= (abs(n.x) + abs(n.y) + abs(n.z));
n.xy = n.z >= 0.0 ? n.xy : octahedronWrap(n.xy);
#ifdef _Probe1
float dist = distanceBox(mpos.xyz, probeVolumeCenter, probeVolumeSize);
float mask_probe = probeID;
if (probeID > 0) {
const float eps = 0.00001;
mask_probe += clamp(0.5 + dist * 3.0, 0, 1.0 - eps);
}
gl_FragData[0] = vec4(n.xy, occlusion, mask_probe);
#else
gl_FragData[0] = vec4(n.xy, occlusion, mask);
#endif
gl_FragData[1] = vec4(baseColor.rgb, packFloat(roughness, metalness));
}

View file

@ -37,6 +37,26 @@
"id": "skinBones",
"link": "_skinBones",
"ifdef": ["_Skinning"]
},
{
"id": "probeID",
"link": "_probeID",
"ifdef": ["_Probe1"]
},
{
"id": "M",
"link": "_modelMatrix",
"ifdef": ["_Probe1"]
},
{
"id": "probeVolumeCenter",
"link": "_probeVolumeCenter",
"ifdef": ["_Probe1"]
},
{
"id": "probeVolumeSize",
"link": "_probeVolumeSize",
"ifdef": ["_Probe1"]
}
],
"vertex_shader": "deferred.vert.glsl",

View file

@ -36,6 +36,11 @@ uniform vec4 albedo_color;
uniform float skinBones[50 * 12];
#endif
#ifdef _Probe1
uniform mat4 M;
#endif
out vec4 mvpposition;
#ifdef _AMTex
out vec2 texCoord;
@ -48,6 +53,10 @@ out mat3 TBN;
out vec3 normal;
#endif
#ifdef _Probe1
out vec4 mpos;
#endif
#ifdef _Skinning
mat4 getBoneMat(const int boneIndex) {
vec4 v0 = vec4(skinBones[boneIndex * 12 + 0],
@ -104,6 +113,10 @@ void main() {
//MV[2][0] = 0.0; MV[2][1] = 0.0; MV[2][2] = 1.0;
#endif
#ifdef _Probe1
mpos = M * sPos;
#endif
gl_Position = P * MV * sPos;
#ifdef _AMTex

View file

@ -9,19 +9,42 @@ precision mediump float;
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
uniform sampler2D gbuffer1;
uniform sampler2D ssaotex;
uniform sampler2D shadowMap;
uniform sampler2D senvmapRadiance;
uniform sampler2D senvmapIrradiance;
uniform int envmapNumMipmaps;
uniform float envmapStrength;
uniform sampler2D senvmapBrdf;
#ifdef _Probe1
uniform sampler2D senvmapRadiance_1;
uniform sampler2D senvmapIrradiance_1;
// uniform int envmapNumMipmaps_1;
// uniform float envmapStrength_1;
#endif
#ifdef _Probe2
uniform sampler2D senvmapRadiance_2;
uniform sampler2D senvmapIrradiance_2;
#endif
#ifdef _Probe3
uniform sampler2D senvmapRadiance_3;
uniform sampler2D senvmapIrradiance_3;
#endif
#ifdef _Probe4
uniform sampler2D senvmapRadiance_4;
uniform sampler2D senvmapIrradiance_4;
#endif
// uniform sampler2D giblur; // Path-traced
uniform sampler2D ssaotex;
uniform sampler2D shadowMap;
// #ifdef _LTC
// uniform sampler2D sltcMat;
// uniform sampler2D sltcMag;
uniform float envmapStrength;
uniform int envmapNumMipmaps;
// #endif
// uniform mat4 invVP;
uniform mat4 LMVP;
@ -185,7 +208,7 @@ float shadowTest(vec4 lPos) {
lPosH.x = (lPosH.x + 1.0) / 2.0;
lPosH.y = 1.0 - ((-lPosH.y + 1.0) / (2.0));
const float bias = 0.0029;
const float bias = 0.012;
// const float bias = 0.01;
return PCF(vec2(2048, 2048), lPosH.st, lPosH.z - bias);
}
@ -408,6 +431,10 @@ float wardSpecular(vec3 N, vec3 H, float dotNL, float dotNV, float dotNH, vec3 f
}
#endif
vec4 gaussian(vec4 x, vec4 m, float s) {
return exp(-(x-m)*(x-m)/(s*s));
}
void main() {
float depth = texture(gbufferD, texCoord).r * 2.0 - 1.0;
// float depth = 1.0 - g0.a;
@ -453,6 +480,8 @@ void main() {
// visibility = 1.0;
}
// Direct
vec3 direct = diffuseBRDF(albedo, roughness, dotNV, dotNL, dotVH, dotLV) + specularBRDF(f0, roughness, dotNL, dotNH, dotNV, dotVH, dotLH);
// Aniso spec
@ -463,32 +492,103 @@ void main() {
direct = direct * lightColor * lightStrength;
// SSS only masked objects
if (texture(gbuffer0, texCoord).a == 2.0) {
float mask = g0.a;
if (mask == 2.0) {
direct.rgb = direct.rgb * SSSSTransmittance(1.0, 0.005, p, n, lightDir);
}
// Indirect
vec3 indirectDiffuse = texture(senvmapIrradiance, envMapEquirect(n)).rgb;
#ifdef _LDR
indirectDiffuse = pow(indirectDiffuse, vec3(2.2));
#ifdef _Probe1
float probeFactor = mask;
float probeID = floor(probeFactor);
float probeFract = fract(probeFactor);
vec3 indirectDiffuse;
vec3 prefilteredColor;
vec2 envCoord = envMapEquirect(n);
float lod = getMipLevelFromRoughness(roughness);
vec3 reflectionWorld = reflect(-v, n);
vec2 envCoordRefl = envMapEquirect(reflectionWorld);
// Global probe only
if (probeID == 0.0) {
indirectDiffuse = texture(senvmapIrradiance, envCoord).rgb;
prefilteredColor = textureLod(senvmapRadiance, envCoordRefl, lod).rgb;
}
// fract 0 = local probe, 1 = global probe
else if (probeID == 1.0) {
indirectDiffuse = texture(senvmapIrradiance_1, envCoord).rgb * (1.0 - probeFract);
prefilteredColor = textureLod(senvmapRadiance_1, envCoordRefl, lod).rgb * (1.0 - probeFract);
if (probeFract > 0.0) {
indirectDiffuse += texture(senvmapIrradiance, envCoord).rgb * (probeFract);
prefilteredColor += textureLod(senvmapRadiance, envCoordRefl, lod).rgb * (probeFract);
}
}
#ifdef _Probe2
else if (probeID == 2.0) {
indirectDiffuse = texture(senvmapIrradiance_2, envCoord).rgb * (1.0 - probeFract);
prefilteredColor = textureLod(senvmapRadiance_2, envCoordRefl, lod).rgb * (1.0 - probeFract);
if (probeFract > 0.0) {
indirectDiffuse += texture(senvmapIrradiance, envCoord).rgb * (probeFract);
prefilteredColor += textureLod(senvmapRadiance, envCoordRefl, lod).rgb * (probeFract);
}
}
#endif
indirectDiffuse *= albedo;
vec3 reflectionWorld = reflect(-v, n);
#ifdef _Probe3
else if (probeID == 3.0) {
indirectDiffuse = texture(senvmapIrradiance_3, envCoord).rgb * (1.0 - probeFract);
prefilteredColor = textureLod(senvmapRadiance_3, envCoordRefl, lod).rgb * (1.0 - probeFract);
if (probeFract > 0.0) {
indirectDiffuse += texture(senvmapIrradiance, envCoord).rgb * (probeFract);
prefilteredColor += textureLod(senvmapRadiance, envCoordRefl, lod).rgb * (probeFract);
}
}
#endif
#ifdef _Probe4
else if (probeID == 4.0) {
indirectDiffuse = texture(senvmapIrradiance_4, envCoord).rgb * (1.0 - probeFract);
prefilteredColor = textureLod(senvmapRadiance_4, envCoordRefl, lod).rgb * (1.0 - probeFract);
if (probeFract > 0.0) {
indirectDiffuse += texture(senvmapIrradiance, envCoord).rgb * (probeFract);
prefilteredColor += textureLod(senvmapRadiance, envCoordRefl, lod).rgb * (probeFract);
}
}
#endif
#else // No probes
vec3 indirectDiffuse = texture(senvmapIrradiance, envMapEquirect(n)).rgb;
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipLevelFromRoughness(roughness);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
#ifdef _LDR
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
#ifdef _LDR
indirectDiffuse = pow(indirectDiffuse, vec3(2.2));
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
indirectDiffuse = pow(indirectDiffuse, vec3(1.0/2.2));////
prefilteredColor = pow(prefilteredColor, vec3(1.02.2));////
indirectDiffuse *= albedo;
vec2 envBRDF = texture(senvmapBrdf, vec2(roughness, 1.0 - dotNV)).xy;
vec3 indirectSpecular = prefilteredColor * (f0 * envBRDF.x + envBRDF.y);
vec3 indirect = indirectDiffuse + indirectSpecular;
indirect = indirect * lightColor * lightStrength * envmapStrength;
float occlusion = g0.b;
vec4 outColor = vec4(vec3(direct * visibility + indirect * ao * occlusion), 1.0);
vec4 outColor = vec4(vec3(direct * visibility + indirect * ao * occlusion), 1.0);
// Path-traced
// vec4 nois = texture(giblur, texCoord);
// nois.rgb = pow(nois.rgb, vec3(1.0 / 2.2));
// indirect = nois.rgb;
// vec4 outColor = vec4(vec3(direct * visibility + indirect * 3.0 * ao * occlusion), 1.0);
// LTC

View file

@ -65,6 +65,46 @@
"id": "envmapNumMipmaps",
"link": "_envmapNumMipmaps"
},
{
"id": "senvmapIrradiance_1",
"link": "_envmapIrradiance_1",
"ifdef": ["_Probe1"]
},
{
"id": "senvmapRadiance_1",
"link": "_envmapRadiance_1",
"ifdef": ["_Probe1"]
},
{
"id": "senvmapIrradiance_2",
"link": "_envmapIrradiance_2",
"ifdef": ["_Probe2"]
},
{
"id": "senvmapRadiance_2",
"link": "_envmapRadiance_2",
"ifdef": ["_Probe2"]
},
{
"id": "senvmapIrradiance_3",
"link": "_envmapIrradiance_3",
"ifdef": ["_Probe3"]
},
{
"id": "senvmapRadiance_3",
"link": "_envmapRadiance_3",
"ifdef": ["_Probe3"]
},
{
"id": "senvmapIrradiance_4",
"link": "_envmapIrradiance_4",
"ifdef": ["_Probe4"]
},
{
"id": "senvmapRadiance_4",
"link": "_envmapRadiance_4",
"ifdef": ["_Probe4"]
},
{
"id": "sltcMat",
"link": "_ltcMat",

View file

@ -10,70 +10,71 @@ uniform vec3 eye;
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);
//vec3 roomCubeMin = vec3(0.0, 0.0, 0.0);
//vec3 roomCubeMax = vec3(1.0, 1.0, 1.0);
vec3 origin;
vec3 ray;
vec3 colorMask = vec3(1.0);
vec3 accumulatedColor = vec3(0.0);
uniform vec3 light;
uniform vec3 sphereCenter0;
uniform float sphereRadius0;
uniform vec3 sphereColor0;
uniform vec3 sphereCenter1;
uniform float sphereRadius1;
uniform vec3 sphereColor1;
uniform vec3 sphereCenter2;
uniform float sphereRadius2;
uniform vec3 sphereColor2;
uniform vec3 sphereCenter3;
uniform float sphereRadius3;
uniform vec3 sphereColor3;
uniform vec3 sphereCenter4;
uniform float sphereRadius4;
uniform vec3 sphereColor4;
uniform vec3 sphereCenter5;
uniform float sphereRadius5;
uniform vec3 sphereColor5;
uniform vec3 sphereCenter6;
uniform float sphereRadius6;
uniform vec3 sphereColor6;
uniform vec3 sphereCenter7;
uniform float sphereRadius7;
uniform vec3 sphereColor7;
uniform vec3 sphereCenter8;
uniform float sphereRadius8;
uniform vec3 sphereColor8;
uniform vec3 sphereCenter9;
uniform float sphereRadius9;
uniform vec3 sphereColor9;
uniform vec3 sphereCenter10;
uniform float sphereRadius10;
uniform vec3 sphereColor10;
uniform vec3 cubeCenter0;
uniform vec3 cubeSize0;
uniform vec3 cubeColor0;
uniform vec3 cubeCenter1;
uniform vec3 cubeSize1;
uniform vec3 cubeColor1;
uniform vec3 cubeCenter2;
uniform vec3 cubeSize2;
uniform vec3 cubeColor2;
uniform vec3 cubeCenter3;
uniform vec3 cubeSize3;
uniform vec3 cubeColor3;
uniform vec3 cubeCenter4;
uniform vec3 cubeSize4;
uniform vec3 cubeColor4;
uniform vec3 cubeCenter5;
uniform vec3 cubeSize5;
uniform vec3 cubeColor5;
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) {
uniform vec3 sphereColor11;
vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeCenter, vec3 cubeSize) {
vec3 cubeMin = cubeCenter - cubeSize;
vec3 cubeMax = cubeCenter + cubeSize;
vec3 tMin = (cubeMin - origin) / ray;
vec3 tMax = (cubeMax - origin) / ray;
vec3 t1 = min(tMin, tMax);
@ -83,14 +84,16 @@ vec2 intersectCube(vec3 origin, vec3 ray, vec3 cubeMin, vec3 cubeMax) {
return vec2(tNear, tFar);
}
vec3 normalForCube(vec3 hit, vec3 cubeMin, vec3 cubeMax) {
vec3 normalForCube(vec3 hit, vec3 cubeCenter, vec3 cubeSize) {
vec3 cubeMin = cubeCenter - cubeSize;
vec3 cubeMax = cubeCenter + cubeSize;
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);
return vec3(0.0, 0.0, 1.0);
}
float intersectSphere(vec3 origin, vec3 ray, vec3 sphereCenter, float sphereRadius) {
@ -111,8 +114,11 @@ vec3 normalForSphere(vec3 hit, vec3 sphereCenter, float 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);
// return fract(sin(dot(texCoord.xyx + seed, scale)) * 43758.5453 + seed);
float d = 43758.5453;
float dt = dot(texCoord.xyx + seed,scale);
float sn = mod(dt,3.1415926);
return fract(sin(sn) * d);
}
vec3 cosineWeightedDirection(float seed, vec3 normal) {
@ -125,7 +131,7 @@ vec3 cosineWeightedDirection(float seed, vec3 normal) {
if (abs(normal.x) < 0.5) {
sdir = cross(normal, vec3(1.0, 0.0, 0.0));
}
else {
else {
sdir = cross(normal, vec3(0.0, 1.0, 0.0));
}
tdir = cross(normal, sdir);
@ -181,72 +187,30 @@ float shadow(vec3 origin, vec3 ray) {
float tSphere10 = intersectSphere(origin, ray, sphereCenter10, sphereRadius10);
if (tSphere10 < 1.0) return 0.0;
vec2 tCube0 = intersectCube(origin, ray, cubeCenter0, cubeSize0);
if (tCube0.x > 0.0 && tCube0.x < 1.0 && tCube0.x < tCube0.y) return 0.0;
vec2 tCube1 = intersectCube(origin, ray, cubeCenter1, cubeSize1);
if (tCube1.x > 0.0 && tCube1.x < 1.0 && tCube1.x < tCube1.y) return 0.0;
vec2 tCube2 = intersectCube(origin, ray, cubeCenter2, cubeSize2);
if (tCube2.x > 0.0 && tCube2.x < 1.0 && tCube2.x < tCube2.y) return 0.0;
vec2 tCube3 = intersectCube(origin, ray, cubeCenter3, cubeSize3);
if (tCube3.x > 0.0 && tCube3.x < 1.0 && tCube3.x < tCube3.y) return 0.0;
vec2 tCube4 = intersectCube(origin, ray, cubeCenter4, cubeSize4);
if (tCube4.x > 0.0 && tCube4.x < 1.0 && tCube4.x < tCube4.y) return 0.0;
vec2 tCube5 = intersectCube(origin, ray, cubeCenter5, cubeSize5);
if (tCube5.x > 0.0 && tCube5.x < 1.0 && tCube5.x < tCube5.y) 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);
int doBounce(float time, vec3 light, int bounce) {
// compute the intersection with everything
float tSphere0 = intersectSphere(origin, ray, sphereCenter0, sphereRadius0);
float tSphere1 = intersectSphere(origin, ray, sphereCenter1, sphereRadius1);
@ -259,29 +223,16 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
float tSphere8 = intersectSphere(origin, ray, sphereCenter8, sphereRadius8);
float tSphere9 = intersectSphere(origin, ray, sphereCenter9, sphereRadius9);
float tSphere10 = intersectSphere(origin, ray, sphereCenter10, sphereRadius10);
vec2 tCube0 = intersectCube(origin, ray, cubeCenter0, cubeSize0);
vec2 tCube1 = intersectCube(origin, ray, cubeCenter1, cubeSize1);
vec2 tCube2 = intersectCube(origin, ray, cubeCenter2, cubeSize2);
vec2 tCube3 = intersectCube(origin, ray, cubeCenter3, cubeSize3);
vec2 tCube4 = intersectCube(origin, ray, cubeCenter4, cubeSize4);
vec2 tCube5 = intersectCube(origin, ray, cubeCenter5, cubeSize5);
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;
@ -294,25 +245,13 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
if (tSphere8 < t) t = tSphere8;
if (tSphere9 < t) t = tSphere9;
if (tSphere10 < t) t = tSphere10;
if (tCube0.x > 0.0 && tCube0.x < tCube0.y && tCube0.x < t) t = tCube0.x;
if (tCube1.x > 0.0 && tCube1.x < tCube1.y && tCube1.x < t) t = tCube1.x;
if (tCube2.x > 0.0 && tCube2.x < tCube2.y && tCube2.x < t) t = tCube2.x;
if (tCube3.x > 0.0 && tCube3.x < tCube3.y && tCube3.x < t) t = tCube3.x;
if (tCube4.x > 0.0 && tCube4.x < tCube4.y && tCube4.x < t) t = tCube4.x;
if (tCube5.x > 0.0 && tCube5.x < tCube5.y && tCube5.x < t) t = tCube5.x;
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;
@ -320,52 +259,44 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
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;
if (t == 10000.0) {
//break;
return 0;
}
else {
int aa = 0;
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);
else if (t == tSphere0) { normal = normalForSphere(hit, sphereCenter0, sphereRadius0); surfaceColor = sphereColor0; }
else if (t == tSphere1) { normal = normalForSphere(hit, sphereCenter1, sphereRadius1); surfaceColor = sphereColor1; }
else if (t == tSphere2) { normal = normalForSphere(hit, sphereCenter2, sphereRadius2); surfaceColor = sphereColor2; }
else if (t == tSphere3) { normal = normalForSphere(hit, sphereCenter3, sphereRadius3); surfaceColor = sphereColor3; }
else if (t == tSphere4) { normal = normalForSphere(hit, sphereCenter4, sphereRadius4); surfaceColor = sphereColor4; }
else if (t == tSphere5) { normal = normalForSphere(hit, sphereCenter5, sphereRadius5); surfaceColor = sphereColor5; }
else if (t == tSphere6) { normal = normalForSphere(hit, sphereCenter6, sphereRadius6); surfaceColor = sphereColor6; }
else if (t == tSphere7) { normal = normalForSphere(hit, sphereCenter7, sphereRadius7); surfaceColor = sphereColor7; }
else if (t == tSphere8) { normal = normalForSphere(hit, sphereCenter8, sphereRadius8); surfaceColor = sphereColor8; }
else if (t == tSphere9) { normal = normalForSphere(hit, sphereCenter9, sphereRadius9); surfaceColor = sphereColor9; }
else if (t == tSphere10) { normal = normalForSphere(hit, sphereCenter10, sphereRadius10); surfaceColor = sphereColor10; }
// 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 == tCube0.x) { if (tCube0.x < tCube0.y) normal = normalForCube(hit, cubeCenter0, cubeSize0); surfaceColor = cubeColor0; }
// 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 == tCube1.x) { if (tCube1.x < tCube1.y) normal = normalForCube(hit, cubeCenter1, cubeSize1); surfaceColor = cubeColor1; }
// 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 == tCube2.x) { if (tCube2.x < tCube2.y) normal = normalForCube(hit, cubeCenter2, cubeSize2); surfaceColor = cubeColor2; }
// 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 == tCube3.x) { if (tCube3.x < tCube3.y) normal = normalForCube(hit, cubeCenter3, cubeSize3); surfaceColor = cubeColor3; }
// 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 == tCube4.x) { if (tCube4.x < tCube4.y) normal = normalForCube(hit, cubeCenter4, cubeSize4); surfaceColor = cubeColor4; }
// 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 == tCube5.x) { if (tCube5.x < tCube5.y) normal = normalForCube(hit, cubeCenter5, cubeSize5); surfaceColor = cubeColor5; }
else if (t == tSphere11) { normal = normalForSphere(hit, sphereCenter11, sphereRadius11); surfaceColor = sphereColor11; }
ray = reflect(ray, normal);
@ -376,33 +307,57 @@ vec3 calculateColor(float time, vec3 origin, vec3 ray, vec3 light) {
// 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);
//float diffuse = max(0.0, dot(normalize(toLight), normal));
float diffuse = max(0.0, dot(normalize(toLight), normal)) / dot(toLight,toLight);
// do light bounce
colorMask *= surfaceColor;
accumulatedColor += colorMask * (0.5 * diffuse * shadowIntensity);
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
//if (bounce > 0) {
// trace a shadow ray to the light
float shadowIntensity = 1.0;//shadow(hit + normal * 0.0001, toLight);
accumulatedColor += colorMask * (0.5 * diffuse * shadowIntensity);
accumulatedColor += colorMask * specularHighlight * shadowIntensity;
//}
// calculate next origin
origin = hit;
}
return 0;
}
vec3 calculateColor(float time, vec3 _origin, vec3 _ray, vec3 light) {
//vec3 colorMask = vec3(1.0);
//vec3 accumulatedColor = vec3(0.0);
origin = _origin;
ray = _ray;
// main raytracing loop
//for (int bounce = 0; bounce < 2; bounce++) {
int a;
a = doBounce(time, light, 0);
a = doBounce(time, light, 1);
a = doBounce(time, light, 2);
//}
return accumulatedColor;
}
void main() {
float time = timeSinceStart;
float time = 0.0;//timeSinceStart;
//timeSinceStart % 46735.275 ) / 1000;
vec3 col = vec3(0.0);
const int samples = 1;
vec3 newLight;
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;
}
//for (int i = 0; i < samples; i++) {
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);
gl_FragColor.rgb = pow(gl_FragColor.rgb * 0.7, vec3(1.0 / 2.2));
}

View file

@ -20,6 +20,14 @@
{
"id": "timeSinceStart",
"link": "_time"
},
{
"id": "eye",
"link": "_cameraPosition"
},
{
"id": "light",
"link": "_lightPosition"
}
],
"texture_params": [],