Commit 3c5c9e1a authored by Johannes Braun's avatar Johannes Braun
Browse files

Removed buffers.glsl in favor of local trace buffer and a Scene struct...

Removed buffers.glsl in favor of local trace buffer and a Scene struct containing bindless buffer pointers.
parent cd98d22e
......@@ -4,12 +4,12 @@ Size=353,64
Collapsed=0
[Scene]
Pos=2,70
Pos=0,72
Size=352,837
Collapsed=0
[Settings]
Pos=1128,0
Pos=1128,-2
Size=311,899
Collapsed=0
#ifndef INCLUDE_PATHTRACER_BUFFERS_GLSL
#define INCLUDE_PATHTRACER_BUFFERS_GLSL
#include <util/scene/light.glsl>
#include <util/scene/mesh.glsl>
#include <util/scene/material.glsl>
#include <util/tracing/bvh_node.glsl>
#include <util/tracing/tracing.glsl>
layout(std430) restrict readonly buffer lights_buffer
{
Light lights_data[];
};
layout(std430) restrict readonly buffer mesh_buffer
{
Mesh meshes_data[];
};
layout(std430) restrict readonly buffer object_bvh_buffer
{
BVHNode global_bvh_nodes_data[];
};
layout(std430) restrict readonly buffer object_bvh_id_buffer
{
uint mesh_ids_data[];
};
layout(std430) restrict readonly buffer material_buffer
{
Material materials_data[];
};
layout(std430) buffer trace_buffer
{
Trace traces_data[];
};
#endif //!INCLUDE_PATHTRACER_BUFFERS_GLSL
#ifndef INCLUDE_PATHTRACER_DATASTRUCTURE_GLSL
#define INCLUDE_PATHTRACER_DATASTRUCTURE_GLSL
#include <pathtracer/buffers.glsl>
#include <util/scene/mesh.glsl>
#include <util/tracing/bvh_node.glsl>
#include <util/tracing/linespace.glsl>
#include <util/tracing/scene.glsl>
#include <pathtracer/data/mesh_bvh.glsl>
#include <pathtracer/data/mesh_linespace.glsl>
uniform bool use_global_bvh;
bool traverseObjects(const in Ray ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min, bool force_bvh = false);
bool traverseObjects(const in Scene scene, const in Ray ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min, bool force_bvh = false);
bool nearestIntersection(const in Ray ray, inout Hit hit, bool force_bvh = false)
bool nearestIntersection(const in Scene scene, const in Ray ray, inout Hit hit, bool force_bvh = false)
{
float t_min = FLT_MAX;
return traverseObjects(ray, false, FLT_MAX, hit, t_min, force_bvh);
return scene.traverseObjects(ray, false, FLT_MAX, hit, t_min, force_bvh);
}
bool intersectsAny(const in Ray ray, const in float max_distance, bool force_bvh = false)
bool intersectsAny(const in Scene scene, const in Ray ray, const in float max_distance, bool force_bvh = false)
{
float t_min = max_distance;
Hit unused_hit;
return traverseObjects(ray, true, max_distance, unused_hit, t_min, force_bvh);
return scene.traverseObjects(ray, true, max_distance, unused_hit, t_min, force_bvh);
}
int smallestAxis(const in vec3 vector)
......@@ -48,16 +49,39 @@ int smallestAxis(const in vec3 vector)
}
}
bool traverseObjects(const in Ray ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min, bool force_bvh = false)
Mesh getMesh(const in Scene scene, int index)
{
Mesh mesh;
mesh.vertices = scene.meshes[index].vertices;
mesh.triangles = scene.meshes[index].triangles;
mesh.nodes = scene.meshes[index].nodes;
mesh.material = scene.meshes[index].material;
mesh.grid_linespace.linespaces = scene.meshes[index].grid_linespace.linespaces;
mesh.grid_linespace.grid_resolution = scene.meshes[index].grid_linespace.grid_resolution;
mesh.grid_linespace.num_linespaces = scene.meshes[index].grid_linespace.num_linespaces;
//uint material;
mesh.id = scene.meshes[index].id;
mesh.transformation = scene.meshes[index].transformation;
mesh.inverse_transformation = scene.meshes[index].inverse_transformation;
mesh.normal_matrix = scene.meshes[index].normal_matrix;
return mesh;
}
bool traverseObjects(const in Scene scene, const in Ray ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min, bool force_bvh = false)
{
if(!use_global_bvh)
{
float current_t = t_min;
bool hit_triangle = false;
Hit unused;
for(int i=0; i<meshes_data.length(); ++i)
for(int i=0; i<scene.num_meshes; ++i)
{
const Mesh mesh = meshes_data[i];
const Mesh mesh = getMesh(scene, i);
if(force_bvh)
{
if(mesh.traverseBVH(ray.makeRelative(mesh), use_first, current_t, false, hit, unused, t_min)){
......@@ -127,7 +151,7 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
float t = t_min;
float max_dist = max_distance;
// Check once the AABB for the whole scene
bool hit_scene = global_bvh_nodes_data.length() != 0 && ray.intersectsBounds(global_bvh_nodes_data[0].bounds, max_distance);
bool hit_scene = scene.num_meshes != 0 && ray.intersectsBounds(scene.bvh_nodes[0].bounds, max_distance);
bool hit_triangle = false;
int current_node = 0;
......@@ -137,13 +161,13 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
while (hit_scene)
{
if (global_bvh_nodes_data[current_node].type == 0) //Inner node.
if (scene.bvh_nodes[current_node].type == 0) //Inner node.
{
int id_left = int(global_bvh_nodes_data[current_node].left_idx);
bool hit_left = ray.intersectsBounds(global_bvh_nodes_data[id_left].bounds, max_distance);
int id_left = int(scene.bvh_nodes[current_node].left_idx);
bool hit_left = ray.intersectsBounds(scene.bvh_nodes[id_left].bounds, max_distance);
int id_right = int(global_bvh_nodes_data[current_node].right_idx);
bool hit_right = ray.intersectsBounds(global_bvh_nodes_data[id_right].bounds, max_distance);
int id_right = int(scene.bvh_nodes[current_node].right_idx);
bool hit_right = ray.intersectsBounds(scene.bvh_nodes[id_right].bounds, max_distance);
//both hit
if (hit_left && hit_right)
......@@ -179,13 +203,13 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
//shorten ray if closer intersection found.
//intersect triangles
int start = int(global_bvh_nodes_data[current_node].left_idx);
int end = int(global_bvh_nodes_data[current_node].right_idx);
int start = int(scene.bvh_nodes[current_node].left_idx);
int end = int(scene.bvh_nodes[current_node].right_idx);
float current_t = t_min;
for (int i = start; i <= end; i++)
{
const Mesh mesh = meshes_data[i];
const Mesh mesh = getMesh(scene, i);
if(force_bvh)
{
if(mesh.traverseBVH(ray.makeRelative(mesh), use_first, current_t, false, hit, unused, t_min)){
......@@ -259,12 +283,12 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
return hit_triangle;
}
current_node = int(global_bvh_nodes_data[current_node].parent);
current_node = int(scene.bvh_nodes[current_node].parent);
bitstack = bitstack >> 1;
}
//Use other (right) sibling from the left child of the branched tree node.
current_node = int(global_bvh_nodes_data[global_bvh_nodes_data[current_node].parent].right_idx);
current_node = int(scene.bvh_nodes[scene.bvh_nodes[current_node].parent].right_idx);
bitstack = bitstack ^ 1;
}
......
......@@ -159,14 +159,11 @@ bool traverseLineSpace(const in Mesh mesh, int index, const in Ray local_ray, co
{
nearer.triangle = near_data;
nearer.mesh = mesh.id;
if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
{
if(t > 0 && t < max_distance && t < t_min){
hit = nearer;
t_min = t;
//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
return true;
}
if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y) && t > 0 && t < max_distance && t < t_min){
hit = nearer;
t_min = t;
//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
return true;
}
}
......@@ -175,16 +172,11 @@ bool traverseLineSpace(const in Mesh mesh, int index, const in Ray local_ray, co
{
nearer.triangle = near_data;
nearer.mesh = mesh.id;
if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
{
//float farthest_distance = t;
if(t > 0 && t < max_distance && t < t_min){
hit = nearer;
t_min = t;
//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
return true;
}
if(loc.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y) && t > 0 && t < max_distance && t < t_min){
hit = nearer;
t_min = t;
//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
return true;
}
}
......
......@@ -6,16 +6,20 @@
#include <util/scene/camera.glsl>
#include <util/math/random.glsl>
#include <pathtracer/buffers.glsl>
#include <pathtracer/data/mesh_datastructure.glsl>
layout(local_size_variable) in;
layout(rgba32f) uniform image2D u_render_target;
uniform Camera u_camera;
uniform int random_seed;
uniform bool use_linespace = false;
uniform Scene scene;
layout(std430) buffer trace_buffer
{
Trace traces_data[];
};
uniform struct
{
bool u_random_subpixel; //defaults to false.
......@@ -30,7 +34,7 @@ void main()
int id = target_size.x * int(gl_GlobalInvocationID.y) + int(gl_GlobalInvocationID.x);
vec2 random = settings.u_random_subpixel ? vec2(0, 0) : rand2D(random_seed + id, target_size.x*target_size.y);
traces_data[id].ray = u_camera.getRayFromPixel(vec2(gl_GlobalInvocationID.xy), random, vec2(target_size));
traces_data[id].ray = scene.camera.getRayFromPixel(vec2(gl_GlobalInvocationID.xy), random, vec2(target_size));
traces_data[id].hit.invalidate();
traces_data[id].ray.nearestIntersection(traces_data[id].hit, !use_linespace);
scene.nearestIntersection(traces_data[id].ray, traces_data[id].hit, !use_linespace);
}
......@@ -3,17 +3,20 @@
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_compute_variable_group_size : require
#include <util/scene/camera.glsl>
#include <util/tracing/scene.glsl>
#include <util/math/random.glsl>
#include <pathtracer/buffers.glsl>
layout(rgba32f) uniform image2DMS u_gbuffer_texture_01;
layout(rgba32f) uniform image2D u_render_target;
uniform Camera u_camera;
uniform int random_seed;
uniform int samples;
uniform Scene scene;
layout(std430) buffer trace_buffer
{
Trace traces_data[];
};
layout(local_size_variable) in;
void main()
......@@ -27,7 +30,7 @@ void main()
vec2 pixel = vec2(id%target_size.x, id/target_size.x) + random;
vec4 texel_01 = u_gbuffer_texture_01.imageLoad(ivec2(pixel), int(random.x * samples));
traces_data[id].ray = u_camera.getRayFromPixel(pixel, random, vec2(target_size));
traces_data[id].ray = scene.camera.getRayFromPixel(pixel, random, vec2(target_size));
traces_data[id].hit.invalidate();
if (length(texel_01) != 0) {
......
......@@ -9,7 +9,6 @@
#include <util/tracing/tracing.glsl>
#include <util/tracing/linespace.glsl>
#include <pathtracer/data/mesh_bvh.glsl>
#include <pathtracer/buffers.glsl>
layout(local_size_variable) in;
......
......@@ -11,43 +11,36 @@
#include <util/image.glsl>
#include <pathtracer/bsdf.glsl>
#include <pathtracer/buffers.glsl>
#include <pathtracer/data/mesh_datastructure.glsl>
layout(local_size_variable) in;
//In this texture, the colors will all just be added up. The final render target color is then the
//color value of this texture divided by the current sample count.
uniform struct
{
layout(rgba32f) image2D render_target;
} textures;
uniform Environment u_environment;
uniform Scene scene;
uniform int random_seed;
subroutine uniform lightSample u_light_sample[4];
const int num_effects = 4;
//Global properties for the pathtracer itself
uniform struct
{
uint num_bounces;
uint current_sample;
float clamp_direct;
float clamp_indirect;
int bounce_thresholds[num_effects];
} u_render_config;
//Global properties for all mesh-local Line Spaces.
uniform struct
uniform int bounce_count = 16;
uniform int bounce_thresholds[num_effects] = int[num_effects]( 4, 6, 12, 1 );
uniform float clamp_direct = 10.f;
uniform float clamp_indirect = 10.f;
uniform float linespace_accuracy = 0.5f;
uniform float linespace_shadow = 0.5f;
uniform float linespace_distance = 10.f;
uniform int linespace_bounces[num_effects] = int[num_effects]( 3, 3, 3, 1 );
uniform int samples_current = 0;
uniform int sampels_max = 80000;
uniform int samples_per_frame = 1;
layout(rgba32f) uniform image2D render_target;
layout(std430) buffer trace_buffer
{
float accuracy_quality;
float shadow_quality;
float distance_threshold;
int bounce_thresholds[num_effects];
} u_linespace_properties;
Trace traces_data[];
};
struct LightData
{
......@@ -97,6 +90,7 @@ int iArrayComp(const in int array1[num_effects], const in int array2[num_effects
return array1[i] < array2[i] ? 1 : (array1[i] > array2[i] ? -1 : 0);
}
subroutine uniform lightSample sampleLightRoutines[4];
LightData sampleLight(const in Light light, const in Vertex vertex, const in vec2 random_sample)
{
LightData result;
......@@ -104,7 +98,7 @@ LightData sampleLight(const in Light light, const in Vertex vertex, const in vec
{
if(i==light.type%4)
{
result.sample_succeeded = u_light_sample[i](light, vertex.position.xyz, result.point_on_light, result.light_color, random_sample);
result.sample_succeeded = sampleLightRoutines[i](light, vertex.position.xyz, result.point_on_light, result.light_color, random_sample);
}
}
vec3 non_normal_direction = result.point_on_light - vertex.position.xyz;
......@@ -116,16 +110,16 @@ LightData sampleLight(const in Light light, const in Vertex vertex, const in vec
bool shouldUseBvh(const in Bounce bounce)
{
return (bounce.pdf_accumulation > (1-u_linespace_properties.accuracy_quality))
&& iArrayComp(bounce.bounce_amount, u_linespace_properties.bounce_thresholds, bounce.bsdf_id) == 1
&& bounce.path_distance < u_linespace_properties.distance_threshold;
return (bounce.pdf_accumulation > (1-linespace_accuracy))
&& iArrayComp(bounce.bounce_amount, linespace_bounces, bounce.bsdf_id) == 1
&& bounce.path_distance < linespace_distance;
}
bool shouldUseBvhShadow(const in Bounce bounce)
{
return (bounce.pdf_accumulation > (1-u_linespace_properties.shadow_quality))
&& iArrayComp(bounce.bounce_amount, u_linespace_properties.bounce_thresholds, bounce.bsdf_id) == 1
&& bounce.path_distance < u_linespace_properties.distance_threshold;
return (bounce.pdf_accumulation > (1-linespace_shadow))
&& iArrayComp(bounce.bounce_amount, linespace_bounces, bounce.bsdf_id) == 1
&& bounce.path_distance < linespace_distance;
}
//////////////////////////////////////////////////////////////////////////
......@@ -136,24 +130,24 @@ bool shouldUseBvhShadow(const in Bounce bounce)
bool shade(inout Bounce bounce)
{
float clamp_color_max = mix(u_render_config.clamp_direct, u_render_config.clamp_indirect, bounce.count.clamp(0.f, 1.f));
float clamp_color_max = mix(clamp_direct, clamp_indirect, bounce.count.clamp(0.f, 1.f));
//Sample environment when not hitting anything.
if(!bounce.hit.valid())
{
vec3 environment = bounce.radiance * u_environment.sampleColor(bounce.ray.direction.xyz).rgb;
vec3 environment = bounce.radiance * scene.environment.sampleColor(bounce.ray.direction.xyz).rgb;
bounce.color += clamp(environment, 0, clamp_color_max);
return false;
}
//Get Hit data
const Mesh mesh = meshes_data[bounce.hit.mesh];
const Mesh mesh = scene.meshes[bounce.hit.mesh];
const Vertex vertex = mesh.getVertex(bounce.hit);
const Material material = materials_data[mesh.material];
const Material material = (*mesh.material);
// generate a random sample on each bounce so there won't be any notifiable patterns
const vec2 base_random = vec2(bounce.ray.px, bounce.ray.py) - ivec2(floor(bounce.ray.px), floor(bounce.ray.py));
const ivec2 img_size = textures.render_target.imageSize();
const ivec2 img_size = render_target.imageSize();
const int img_dimen = img_size.x * img_size.y;
const vec2 random_sample = rand2D((random_seed + int(gl_GlobalInvocationID.y * uint(img_size.x) + gl_GlobalInvocationID.x))%img_dimen, img_size.x * img_size.y);
......@@ -167,7 +161,7 @@ bool shade(inout Bounce bounce)
if(i==bsdf_result.bsdf_id)
{
bounce.bounce_amount[i] += 1;
exceeds_bounces = bounce.bounce_amount[i] > u_render_config.bounce_thresholds[i];
exceeds_bounces = bounce.bounce_amount[i] > bounce_thresholds[i];
break;
}
}
......@@ -187,14 +181,14 @@ bool shade(inout Bounce bounce)
return bounce.hit.invalidate();
}
if (lights_data.length() > 0) {
if (scene.num_lights > 0) {
//Select random light.
Light light = lights_data[int(floor(random_sample.x * lights_data.length()))];
Light light = scene.lights[int(floor(random_sample.x * scene.num_lights))];
//And sample it.
LightData data = light.sampleLight(vertex, random_sample);
if (data.sample_succeeded && !data.shadow_test.intersectsAny(data.testing_distance, shouldUseBvhShadow(bounce)))
if (data.sample_succeeded && !scene.intersectsAny(data.shadow_test, data.testing_distance, shouldUseBvhShadow(bounce)))
{
vec3 lighting = data.light_color * bsdf_result.evaluation * bounce.radiance * max(dot(vertex.normal.xyz, normalize(data.shadow_test.direction)), 0.f);
bounce.color += clamp(lighting, 0, clamp_color_max);
......@@ -209,12 +203,12 @@ void trace(inout Bounce bounce)
{
//Invalidate before intersection test so that we don't have to conditionally invalidate afterwards
bounce.hit.invalidate();
bounce.ray.nearestIntersection(bounce.hit, shouldUseBvh(bounce));
scene.nearestIntersection(bounce.ray, bounce.hit, shouldUseBvh(bounce));
}
void main()
{
ivec2 target_size = textures.render_target.imageSize();
ivec2 target_size = render_target.imageSize();
int id = target_size.x * int(gl_GlobalInvocationID.y) + int(gl_GlobalInvocationID.x);
//Discard pixel if it's not visible to avoid artifacts
......@@ -237,15 +231,15 @@ void main()
// Will execute the bounce.shade() method at the very beginning (to shade the primary ray) and then
// continue with first-trace-then-shade until either shade returns false (not hitting something or constribution too low)
// or we exceed the global bounce limit.
for (bounce.count = 1; bounce.shade() && bounce.count <= u_render_config.num_bounces; ++bounce.count) {
for (bounce.count = 1; bounce.shade() && bounce.count <= bounce_count; ++bounce.count) {
bounce.trace();
}
ivec2 pixel = ivec2(bounce.ray.px, bounce.ray.py);
vec4 color = textures.render_target.imageLoad(pixel);
vec4 color = render_target.imageLoad(pixel);
// Divide color storage by sample count to retrieve the final color.
// A float type render target should provide enough precision to not need a secondary color storage.
color = mix(color, vec4(bounce.color, 1), 1 / float(u_render_config.current_sample + 1));
textures.render_target.imageStore(pixel, color);
color = mix(color, vec4(bounce.color, 1), 1 / float(samples_current + 1));
render_target.imageStore(pixel, color);
}
......@@ -6,6 +6,7 @@
#include <util/math/geometry.glsl>
#include <util/tracing/linespace.glsl>
#include <util/tracing/bvh_node.glsl>
#include <util/scene/material.glsl>
////////////////////////////////////////////////////////////////////
////
......@@ -21,13 +22,13 @@ struct Mesh
Vertex* vertices;
Triangle* triangles;
BVHNode* nodes;
int p1[2];
Material* material;
GridLinespaceData grid_linespace;
uint material;
//uint material;
uint id;
int p[2];
int p[3];
mat4 transformation;
mat4 inverse_transformation;
......
#ifndef INCLUDE_UTIL_TRACING_SCENE_GLSL
#define INCLUDE_UTIL_TRACING_SCENE_GLSL
#include <util/tracing/bvh_node.glsl>
#include <util/scene/camera.glsl>
#include <util/scene/mesh.glsl>
#include <util/scene/light.glsl>
#include <util/scene/environment.glsl>
struct Scene
{
BVHNode* bvh_nodes;
Mesh* meshes;
Light* lights;
Environment environment;
Camera camera;
int num_meshes;
int num_lights;
bool global_bvh;
};
#endif //!INCLUDE_UTIL_TRACING_SCENE_GLSL
\ No newline at end of file
......@@ -53,6 +53,6 @@ namespace glare::raytrace
void CameraCollector::apply(core::Program &program)
{
if(!m_cameras.empty())
program.uniformStruct("u_camera", m_cameras[m_active_camera]);
program.uniformStruct("scene.camera", m_cameras[m_active_camera]);
}
}
......@@ -40,7 +40,8 @@ namespace glare::raytrace
}
void LightCollector::apply(core::Program &program)
{
program.storageBuffer("lights_buffer", m_light_buffer);
{
program.uniform("scene.lights", m_lights.empty() ? 0 : m_light_buffer.makeResident(gl::Access::eReadOnly));
program.uniform("scene.num_lights", static_cast<int>(m_lights.size()));
}
}
\ No newline at end of file
......@@ -56,18 +56,15 @@ namespace glare::raytrace
const bool update_mesh_transforms = (flags & DirtyFlags::eMeshTransform);
const bool update_materials = (flags & DirtyFlags::eMaterial);
if (update_meshes || update_mesh_transforms) {
m_meshes.clear();
assign();
}
if (update_materials) {
m_material_buffer.upload(m_materials, gl::BufferUsage::eDynamicRead);
if (m_material_buffer.size() != 0)
m_material_buffer.makeResident(gl::Access::eReadOnly);
}
if (update_meshes || update_mesh_transforms) {
if (update_meshes || update_mesh_transforms || update_materials) {
m_meshes.clear();
assign(update_meshes || update_mesh_transforms);
m_mesh_buffer.upload(m_meshes, gl::BufferUsage::eDynamicRead);
}
}
......@@ -84,11 +81,10 @@ namespace glare::raytrace
void MeshCollector::apply(core::Program &program)
{
program.storageBuffer("mesh_buffer", m_mesh_buffer);
program.storageBuffer("object_bvh_buffer", m_global_bvh.buffer());
program.storageBuffer("object_bvh_id_buffer", m_bvh_id_buffer);
program.storageBuffer("material_buffer", m_material_buffer);
program.uniform("use_global_bvh", m_use_bvh);
program.uniform("scene.meshes", m_meshes.empty() ? 0 : m_mesh_buffer.makeResident(gl::Access::eReadOnly));
program.uniform("scene.bvh_nodes", m_global_bvh.nodes().empty() ? 0 : m_global_bvh.buffer().makeResident(gl::Access::eReadOnly));
program.uniform("scene.num_meshes", static_cast<int>(m_meshes.size()));
program.uniform("scene.global_bvh", m_use_bvh);
}