Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Johannes Braun
glare
Commits
df9f43a3
Commit
df9f43a3
authored
Sep 03, 2017
by
Johannes Braun
Browse files
Removed PT color storage texture and made just about everything dispatch-local.
parent
89cbb3b2
Changes
6
Hide whitespace changes
Inline
Side-by-side
assets/shaders/pathtracer/generators/bvh/bvh_raygenerator.comp
View file @
df9f43a3
...
...
@@ -20,10 +20,6 @@ uniform struct
bool u_random_subpixel; //defaults to false.
} settings;
void generate(int id, ivec2 pixels);
void trace(int id);
void resetImportance(int id);
void main()
{
ivec2 target_size = u_render_target.imageSize();
...
...
@@ -31,26 +27,9 @@ void main()
return;
int id = target_size.x * int(gl_GlobalInvocationID.y) + int(gl_GlobalInvocationID.x);
generate(id, target_size);
trace(id);
resetImportance(id);
}
void generate(int id, ivec2 pixels)
{
traces_data[id].ray = u_camera.getRayFromPixel(vec2(gl_GlobalInvocationID.xy), settings.u_random_subpixel ? vec2(0, 0) : rand2D(random_seed + id, pixels.x*pixels.y), vec2(pixels));
}
void trace(int id)
{
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].hit.invalidate();
bool intersects = nearestIntersection(traces_data[id].ray, traces_data[id].hit, true);
}
void resetImportance(int id)
{
traces_data[id].properties.accuracy_importance = 1.f;
traces_data[id].properties.shadow_importance = 1.f;
traces_data[id].properties.bounce_amount = 0;
traces_data[id].properties.travelled_distance = 0;
bool intersects = traces_data[id].ray.nearestIntersection(traces_data[id].hit, true);
}
assets/shaders/pathtracer/pathtracer.comp
View file @
df9f43a3
...
...
@@ -43,24 +43,43 @@ uniform struct
float distance_threshold;
} u_linespace_properties;
uint getBounceAmount(const in Trace trace, uint id)
struct LightData
{
return (trace.properties.bounce_amount >> (8*id)) & 0xFF;
}
bool sample_succeeded;
Ray shadow_test;
vec3 point_on_light;
vec3 light_color;
float testing_distance;
};
void addBounceAmount(inout Trace trace, uint id, uint am
oun
t)
struct B
oun
ce
{
trace.properties.bounce_amount += (amount & 0xFF) << (8*id);
}
Hit hit;
Ray ray;
vec3 color;
vec3 radiance;
//Threshold properties
float path_distance;
float accuracy_importance;
float shadow_importance;
uint getLSBounceThreshold(uint id)
uint bounce_amount;
int count;
int bsdf_id;
};
uint getPart(uint base, uint index)
{
return (
u_linespace_properties.bounce_thresholds >> (8*id
)) & 0xFF;
return (
base >> (8 * index
)) & 0xFF;
}
uint getBounceThreshold(uint id
)
void addToPart(inout uint base, uint index, uint amount
)
{
return (u_render_config.bounce_thresholds >> (8*id)) & 0xFF
;
base += (amount & 0xFF) << (8 * index)
;
}
//////////////////////////////////////////////////////////////////////////
...
...
@@ -69,26 +88,21 @@ uint getBounceThreshold(uint id)
////
//////////////////////////////////////////////////////////////////////////
void writeRenderTarget(in
t i
d,
vec
4 color
)
LightData sampleLight(const in Light light, const in Vertex vertex, cons
t i
n
vec
2 random_sample
)
{
Trace trace = traces_data[id];
u_render_target.imageStore(ivec2(trace.ray.px, trace.ray.py), vec4(color.rgb, 1));
LightData result;
result.sample_succeeded = u_light_sample[light.type % 4](light, vertex.position.xyz, result.point_on_light, result.light_color, random_sample);
vec3 non_normal_direction = result.point_on_light - vertex.position.xyz;
result.shadow_test.direction = normalize(non_normal_direction);
result.shadow_test.origin = vertex.position.xyz + 1e-2f * vertex.normal.xyz;
return result;
}
void writeColorStore(const in Ray ray, const in vec3 rgb_color, float clamp_color
)
bool shouldUseBvh(const in Bounce bounce
)
{
u_color_store.imageAdd(ivec2(ray.px, ray.py), vec4(rgb_color.clamp(0, clamp_color), 1));
}
vec4 loadColorStore(int id)
{
Trace trace = traces_data[id];
return u_color_store.imageLoad(ivec2(trace.ray.px, trace.ray.py));
}
bool sampleLight(const in Light light, const in vec3 position, out vec3 point_on_light, out vec3 color, const in vec2 random_sample)
{
return u_light_sample[light.type % 4](light, position, point_on_light, color, random_sample);
return (bounce.shadow_importance > (1-u_linespace_properties.shadow_quality))
&& (bounce.bounce_amount.getPart(bounce.bsdf_id) < u_linespace_properties.bounce_thresholds.getPart(bounce.bsdf_id))
&& bounce.path_distance < u_linespace_properties.distance_threshold;
}
//////////////////////////////////////////////////////////////////////////
...
...
@@ -97,96 +111,77 @@ bool sampleLight(const in Light light, const in vec3 position, out vec3 point_on
////
//////////////////////////////////////////////////////////////////////////
bool shade(in
t id, inout vec3 radiance, uint bounce, out uint bsdf_id
)
bool shade(in
out Bounce bounce
)
{
Trace trace = traces_data[id];
Hit hit = trace.hit;
Ray ray = trace.ray;
float clamp_color_max = mix(u_render_config.clamp_direct, u_render_config.clamp_indirect, bounce.clamp(0.f, 1.f));
float clamp_color_max = mix(u_render_config.clamp_direct, u_render_config.clamp_indirect, bounce.count.clamp(0.f, 1.f));
//Sample environment when not hitting anything.
if(!hit.valid())
if(!
bounce.
hit.valid())
{
writeColorStore(ray, radiance * u_environment.sampleColor(ray.direction.xyz).rgb, clamp_color_max);
vec3 environment = bounce.radiance * u_environment.sampleColor(bounce.ray.direction.xyz).rgb;
bounce.color += clamp(environment, 0, clamp_color_max);
return false;
}
//Get Hit data
Mesh mesh = meshes_data[hit.mesh];
Vertex vertex = mesh.getVertex(hit);
Mesh mesh = meshes_data[
bounce.
hit.mesh];
Vertex vertex = mesh.getVertex(
bounce.
hit);
Material material = materials_data[mesh.material];
traces_data[id].properties.travelled_distance += traces_data[id].hit.valid() ? (distance(traces_data[id]
.ray.origin, vertex.position.xyz)
) : FLT_MAX
;
bounce.path_distance += distance(bounce
.ray.origin, vertex.position.xyz);
// generate a random sample on each bounce so there won't be any notifiable patterns
const vec2 base_random = vec2(ray.px, ray.py) - ivec2(floor(ray.px), floor(ray.py));
const vec2 base_random = vec2(
bounce.
ray.px,
bounce.
ray.py) - ivec2(floor(
bounce.
ray.px), floor(
bounce.
ray.py));
const ivec2 img_size = u_render_target.imageSize();
const int img_dimen = img_size.x * img_size.y;
vec2 random_sample = rand2D((random_seed + int(
id
))%img_dimen, img_size.x * img_size.y);
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);
BSDFResult bsdf_result = material.computeBSDF(random_sample, vertex, ray);
BSDFResult bsdf_result = material.computeBSDF(random_sample, vertex,
bounce.
ray);
traces_data[id].addBounceAmount(bsdf_result.bsdf_id, 1);
if(traces_data[id].getBounceAmount(bsdf_result.bsdf_id) > getBounceThreshold(bsdf_result.bsdf_id))
bounce.bsdf_id = int(bsdf_result.bsdf_id);
bounce.bounce_amount.addToPart(bsdf_result.bsdf_id, 1);
if(bounce.bounce_amount.getPart(bsdf_result.bsdf_id) > u_render_config.bounce_thresholds.getPart(bsdf_result.bsdf_id))
{
traces_data[id].hit.invalidate();
return false;
return bounce.hit.invalidate();
}
if(bsdf_result.bsdf_id == eEmit)
{
writeColorStore(ray, radiance * bsdf_result.radiance, clamp_color_max);
traces_data[id].hit.invalidate();
return false;
bounce.color += clamp(bounce.radiance * bsdf_result.radiance, 0, clamp_color_max);
return bounce.hit.invalidate();
}
bool use_bvh = (trace.properties.shadow_importance > (1-u_linespace_properties.shadow_quality))
&& (traces_data[id].getBounceAmount(bsdf_result.bsdf_id) < getLSBounceThreshold(bsdf_result.bsdf_id))
&& traces_data[id].properties.travelled_distance < u_linespace_properties.distance_threshold;
if (lights_data.length() > 0) {
//Select random light.
Light light = lights_data[int(floor(random_sample.x * lights_data.length()))];
vec3 point_on_light;
vec3 light_color;
bool success = sampleLight(light, vertex.position.xyz, point_on_light, light_color, random_sample);
vec3 non_normal_direction = point_on_light - vertex.position.xyz;
Ray shadow_test;
shadow_test.direction = normalize(non_normal_direction);
shadow_test.origin = vertex.position.xyz + 1e-2f * vertex.normal.xyz;
if (success && !shadow_test.intersectsAny(length(non_normal_direction), use_bvh))
//And sample it.
LightData data = light.sampleLight(vertex, random_sample);
if (data.sample_succeeded && !data.shadow_test.intersectsAny(data.testing_distance, shouldUseBvh(bounce)))
{
writeColorStore(ray, light_color * bsdf_result.evaluation * radiance * max(dot(vertex.normal.xyz, normalize(shadow_test.direction)), 0.f), clamp_color_max);
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);
}
}
//Quit if bounces won't be of any use due to low contributions
if (bsdf_result.radiance == vec3(0) || bsdf_result.probability_density <= 1e-5f)
{
traces_data[id].hit.invalidate();
return false;
return bounce.hit.invalidate();
}
traces_data[id].properties
.accuracy_importance *= bsdf_result.probability_density;
traces_data[id].properties
.shadow_importance *= bsdf_result.probability_density;
traces_data[id]
.ray = bsdf_result.generated_ray;
radiance *= clamp(bsdf_result.radiance * angle(bsdf_result.generated_ray, vertex) / bsdf_result.probability_density, 0, 1);
//
bounce
.accuracy_importance *= bsdf_result.probability_density;
bounce
.shadow_importance *= bsdf_result.probability_density;
bounce
.ray = bsdf_result.generated_ray;
bounce.
radiance *= clamp(bsdf_result.radiance * angle(bsdf_result.generated_ray, vertex) / bsdf_result.probability_density, 0, 1);
return true;
}
bool
trace(in
t id, uint last_bsdf_id
)
void
trace(in
out Bounce bounce
)
{
//Invalidate before intersection test so that we don't have to conditionally invalidate afterwards
traces_data[id].hit.invalidate();
//Use a BVH if accuracy is important
bool use_bvh = (traces_data[id].properties.accuracy_importance > (1-u_linespace_properties.accuracy_quality))
&& (traces_data[id].getBounceAmount(last_bsdf_id) < getLSBounceThreshold(last_bsdf_id))
&& traces_data[id].properties.travelled_distance < u_linespace_properties.distance_threshold;
bool intersects = traces_data[id].ray.nearestIntersection(traces_data[id].hit, use_bvh);
return intersects;
bounce.hit.invalidate();
bounce.ray.nearestIntersection(bounce.hit, shouldUseBvh(bounce));
}
void main()
...
...
@@ -198,19 +193,33 @@ void main()
if (!(int(gl_GlobalInvocationID.x) < target_size.x && int(gl_GlobalInvocationID.y) < target_size.y))
return;
//Initial radiance weight.
vec3 radiance = vec3(1);
//Shade the primary ray hit which was generated by the RayGenerator before the render dispatch call.
uint last_bsdf_id;
bool success = shade(id, radiance, 0, last_bsdf_id);
//Then shade all valid hits as long as they bounce around happily in the scene.
for (int bounce = 0; bounce < u_render_config.num_bounces && success; ++bounce) {
success = trace(id, last_bsdf_id);
success = bool(uint(success) & uint(shade(id, radiance, bounce + 1, last_bsdf_id)));
// Get the trace generated by the external primary-ray-generator and initialize the Bounce struct.
Trace current = traces_data[id];
Bounce bounce;
bounce.hit = current.hit;
bounce.ray = current.ray;
//Threshold properties
bounce.path_distance = 0;
bounce.accuracy_importance = 1.f;
bounce.shadow_importance = 1.f;
bounce.bounce_amount = 0;
bounce.color = vec3(0);
bounce.radiance = vec3(1);
// Nifty for-loop trick. :P
// 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) {
bounce.trace();
}
//Divide color storage by sample count to retrieve the final color.
writeRenderTarget(id, loadColorStore(id) / (u_render_config.current_sample + 1));
ivec2 pixel = ivec2(bounce.ray.px, bounce.ray.py);
vec4 color = u_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));
u_render_target.imageStore(pixel, color);
}
assets/shaders/util/tracing/tracing.glsl
View file @
df9f43a3
...
...
@@ -35,14 +35,14 @@ struct Hit
/*
@bytesize 16
*/
struct
TraceProperties
{
float
accuracy_importance
;
float
shadow_importance
;
uint
bounce_amount
;
float
travelled_distance
;
};
//
struct TraceProperties
//
{
//
float accuracy_importance;
//
float shadow_importance;
//
//
uint bounce_amount;
//
float travelled_distance;
//
};
/*
@bytesize 64
...
...
@@ -53,7 +53,7 @@ struct Trace
Hit
hit
;
//Additional properties for BVH-LS-Hybrid
TraceProperties
properties
;
//
TraceProperties properties;
};
...
...
@@ -78,7 +78,7 @@ Ray makeRelative(const in Ray ray, const in Mesh mesh)
bool
valid
(
const
in
Hit
hit
)
{
return
hit
.
barycentric
.
x
!=
-
1
;
}
void
invalidate
(
inout
Hit
hit
)
{
hit
.
barycentric
.
x
=
-
1
;
}
bool
invalidate
(
inout
Hit
hit
)
{
hit
.
barycentric
.
x
=
-
1
;
return
false
;
}
#define hit__getFromBarycentric(barycentric, triangle, param) (barycentric.x * v1.param + \
barycentric
.
y
*
v2
.
param
+
\
...
...
src/libraries/core/base/program.cpp
View file @
df9f43a3
...
...
@@ -25,7 +25,7 @@ namespace glare::core
gl
::
getProgramInfoLog
(
m_handle
,
log_length
,
&
log_length
,
&
log
[
0
]);
Log_Error
<<
log
;
Log_Error
<<
"
Shader compiled successfully
."
;
Log_Error
<<
"
Error linking the program
."
;
for
(
const
auto
&
shader
:
shaders
)
gl
::
detachShader
(
m_handle
,
shader
->
id
());
...
...
src/libraries/raytrace/tracer/pathtracer.cpp
View file @
df9f43a3
...
...
@@ -25,7 +25,6 @@ namespace glare::raytrace
core
::
Context
::
current
().
messages
()
->
addObserver
(
this
,
tags
::
scene
);
m_render_target
=
std
::
make_unique
<
core
::
Texture
>
(
core
::
Texture
::
Target
::
e2D
,
core
::
Texture
::
StoreFormat
::
eRGBA32Float
);
m_color_storage
=
std
::
make_unique
<
core
::
Texture
>
(
core
::
Texture
::
Target
::
e2D
,
core
::
Texture
::
StoreFormat
::
eRGBA32Float
);
if
(
collector
)
initialize
(
collector
);
...
...
@@ -98,10 +97,8 @@ namespace glare::raytrace
m_trace_buffer
.
reserve
<
Trace
>
(
width
*
height
,
gl
::
BufferUsage
::
eDynamicCopy
);
m_render_target
=
std
::
make_unique
<
core
::
Texture
>
(
core
::
Image
<
float
>
({
static_cast
<
int
>
(
width
),
static_cast
<
int
>
(
height
)
},
4
));
m_color_storage
=
std
::
make_unique
<
core
::
Texture
>
(
core
::
Image
<
float
>
({
static_cast
<
int
>
(
width
),
static_cast
<
int
>
(
height
)
},
4
));
m_render_shader
->
uniform
(
"u_render_target"
,
m_render_target
->
imageAddress
(
gl
::
Access
::
eReadWrite
));
m_render_shader
->
uniform
(
"u_color_store"
,
m_color_storage
->
imageAddress
(
gl
::
Access
::
eReadWrite
));
m_render_shader
->
storageBuffer
(
"trace_buffer"
,
m_trace_buffer
);
m_samples_current
=
0
;
...
...
@@ -110,7 +107,6 @@ namespace glare::raytrace
if
(
m_samples_current
==
0
)
{
m_collector
->
collect
();
m_color_storage
->
clear
(
0
);
}
for
(
unsigned
sample
=
0
;
sample
<
m_samples_per_frame
;
sample
++
)
{
...
...
src/libraries/raytrace/tracer/pathtracer.h
View file @
df9f43a3
...
...
@@ -120,7 +120,6 @@ namespace glare::raytrace
std
::
unique_ptr
<
core
::
Program
>
m_render_shader
;
std
::
unique_ptr
<
core
::
Texture
>
m_render_target
;
std
::
unique_ptr
<
core
::
Texture
>
m_color_storage
;
core
::
Buffer
m_trace_buffer
;
std
::
shared_ptr
<
SceneCollector
>
m_collector
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment