Commit 0d85c7ca authored by Johannes Braun's avatar Johannes Braun
Browse files

Better unified shaders. (OpenGL shading not yet working as expected)

parent 5b985c92
#version 430
in vec3 out_texcoord;
uniform samplerCube u_cube_map;
layout(location=0) out vec4 out_color;
layout(location = 1) out vec4 out_final_normal;
void main()
{
out_color = vec4(texture(u_cube_map, out_texcoord).rgb, 1);
out_final_normal = vec4(0,0,0,1);
}
\ No newline at end of file
#version 430
layout(location=0) in vec4 in_position;
layout(location=1) in vec4 in_normal;
layout(location=2) in vec2 in_texcoord;
uniform mat4 u_view_projection;
uniform mat4 u_model;
out vec3 out_texcoord;
void main()
{
gl_Position = (u_view_projection * u_model * in_position).xyzw;
out_texcoord = in_position.xyz;
}
\ No newline at end of file
......@@ -4,11 +4,18 @@ in vec3 out_texcoord;
uniform samplerCube u_cube_map;
layout(location = 0) out vec4 out_color;
layout(location = 1) out vec4 out_final_normal;
// vec3 base color and float roughness
layout(location = 0) out vec4 output_base_ior;
// vec3 emission color and float metallic
layout(location = 1) out vec4 output_rough_metallic_transmit_emit;
layout(location = 2) out vec4 output_normal;
layout(location = 3) out vec4 output_modelview_position;
layout(location = 4) out vec4 output_world_position;
void main()
{
out_color = vec4(texture(u_cube_map, out_texcoord).rgb, 1);
out_final_normal = vec4(0, 0, 0, 1);
}
\ No newline at end of file
output_base_ior = vec4(texture(u_cube_map, out_texcoord).rgb, 1);
output_rough_metallic_transmit_emit = vec4(0);
output_normal = vec4(0, 0, 0, 1);
}
#version 430
layout(location = 6) out vec4 out_final_lighting;
// vec3 base color and float roughness
layout(location = 0) out vec4 output_base_ior;
// vec3 emission color and float metallic
layout(location = 1) out vec4 output_rough_metallic_transmit_emit;
layout(location = 2) out vec4 output_normal;
layout(location = 3) out vec4 output_modelview_position;
layout(location = 4) out vec4 output_world_position;
uniform vec4 u_color;
void main()
{
out_final_lighting = u_color;
output_base_ior.rgb = u_color.rgb;
output_rough_metallic_transmit_emit = vec4(0, 0, 0, 1);
}
#ifndef __BSDF_DIFFUSE_GLH
#define __BDSF_DIFFUSE_GLH
#ifndef INCLUDE_PATHTRACER_BSDF_GLSL
#define INCLUDE_PATHTRACER_BSDF_GLSL
#include <raytracer/basic_structs.glsl>
#include <raytracer/random.glsl>
#include <raytracer/utilities.glsl>
#include <raytracer/properties/ray_transform.glsl>
#include <raytracer/properties/fresnel.glsl>
#include <util/math/random.glsl>
#include <util/math/geometry.glsl>
#include <util/math/ggx.glsl>
#include <screenshader/gbuffer/cook_torrance.glsl>
#include <raytracer/properties/ggx.glsl>
#include <util/scene/material.glsl>
// BSDF IDs
const uint eDiffuse = 0;
......@@ -37,20 +34,14 @@ struct BSDFResult
struct SampledMaterial
{
vec3 base;
vec3 ambient;
vec3 emission;
float ior;
float emission;
float roughness;
float metallic;
float transmission;
float ior;
};
vec3 reflectedDirection(vec3 local_hemi_sample, vec3 normal, vec3 reflected, float roughness)
{
return normalize(localToWorld(local_hemi_sample, normal, reflected));
}
/**
@brief Samples the material at the given vertex. In the process, all available textures will be sampled at the according texture coordinate.
So you will not only get the raw base colors, but also the textured ones.
......@@ -59,9 +50,8 @@ SampledMaterial getMaterialParameters(const in Material material, const in Verte
{
SampledMaterial sampled_material;
sampled_material.base = material.getBase(vertex.texcoord);
sampled_material.ambient = material.getAmbient(vertex.texcoord);
sampled_material.emission = material.getEmission(vertex.texcoord);
sampled_material.emission = material.getEmission(vertex.texcoord);
sampled_material.roughness = material.getRoughness(vertex.texcoord);
sampled_material.metallic = material.getMetallic(vertex.texcoord);
sampled_material.transmission = material.getTransmission(vertex.texcoord);
......@@ -78,9 +68,9 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
//Use the pixel coordinates of the incoming ray.
result.generated_ray = ray_in;
if(sampled_material.emission.rgb != vec3(0))
if(sampled_material.emission != 0)
{
result.radiance = sampled_material.emission.rgb;
result.radiance = sampled_material.emission * sampled_material.base;
result.bsdf_id = eEmit;
return result;
}
......@@ -101,7 +91,7 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
float eta = ior_in / ior_out;
// Transform the computed local microsurface normal to world space along the hit normal
vec3 micro_normal = normalize(toWorld(hemisphere_sample.micro_normal, incoming, normal));
vec3 micro_normal = normalize(localToWorld(hemisphere_sample.micro_normal, incoming, normal));
// Schlick's fresnel approximation with the material's normal response
float normal_response = normalResponse(sampled_material.ior, sampled_material.metallic);
......@@ -120,7 +110,7 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
{
// Sample lambertian diffuse
result.evaluation = (1-sampled_material.metallic)*sampled_material.base * ONE_OVER_PI;
result.generated_ray.direction = normalize(toWorld(randCosineHemisphere(random.x, random.y), incoming, normal));
result.generated_ray.direction = normalize(localToWorld(randCosineHemisphere(random.x, random.y), incoming, normal));
result.probability_density = abs(dot(vec4(result.generated_ray.direction, 0), vertex.normal)) * ONE_OVER_PI;
result.radiance = (1-sampled_material.metallic)*sampled_material.base * ONE_OVER_PI;
result.bsdf_id = eDiffuse;
......@@ -204,4 +194,4 @@ BSDFResult computeBSDF(const in Material material, const in vec2 random, const i
return result;
}
#endif //!__BDSF_DIFFUSE_GLH
#endif //!INCLUDE_PATHTRACER_BSDF_GLSL
#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 __GL_LINESPACE
#define __GL_LINESPACE
#ifndef INCLUDE_PATHTRACER_ANGULAR_LINESPACE_GLSL
#define INCLUDE_PATHTRACER_ANGULAR_LINESPACE_GLSL
#include <raytracer/basic_structs.glsl>
#include <raytracer/buffers.glsl>
#include <raytracer/intersections.glsl>
#include <raytracer/std.glsl>
#include <raytracer/utilities.glsl>
#include <util/scene/mesh.glsl>
#include <util/tracing/intersections.glsl>
#include <util/tracing/tracing.glsl>
const uint face_width_axis[3] = {2, 2, 0};
const uint face_height_axis[3] = {1, 0, 1};
#ifndef USE_ANGULAR_LS
#define USE_ANGULAR_LS
//Include ls data structs with angular definition
#include <util/tracing/linespace.glsl>
#undef USE_ANGULAR_LS
#endif //!USE_ANGULAR_LS
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
bool flip_indices = face != axis;
......@@ -18,22 +20,6 @@ uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
uvec2(at_position[face_width_axis[axis]] / mesh.linespace.patch_size, at_position[face_height_axis[axis]] / mesh.linespace.patch_size)- 1;
}
float getDistance(const in Ray ray, const in Hit hit, inout uint dir_sign)
{
Mesh mesh = b_meshes[hit.mesh];
Triangle triangle = mesh.triangles[hit.triangle];
Vertex v1 = mesh.vertices[triangle.indices[1]];
Vertex v2 = mesh.vertices[triangle.indices[2]];
Vertex v3 = mesh.vertices[triangle.indices[0]];
vec3 vector = hit__getFromBarycentric(hit.barycentric, triangle, position).xyz - ray.origin;
dir_sign = uint(sign(dot(vector, ray.direction)));
return length(vector);
}
struct PatchInfo
{
int face;
......@@ -167,4 +153,4 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
#endif //__GL_LINESPACE
#endif //INCLUDE_PATHTRACER_ANGULAR_LINESPACE_GLSL
#ifndef __GL_BVH
#define __GL_BVH
#ifndef INCLUDE_PATHTRACER_BVH_GLSL
#define INCLUDE_PATHTRACER_BVH_GLSL
#include <raytracer/basic_structs.glsl>
#include <raytracer/buffers.glsl>
#include <raytracer/intersections.glsl>
#include <raytracer/std.glsl>
#include <raytracer/utilities.glsl>
#include <util/scene/mesh.glsl>
#include <util/tracing/intersections.glsl>
#include <util/tracing/bvh_node.glsl>
#include <util/tracing/tracing.glsl>
Bounds getNodeBounds(int index, const in Mesh mesh)
{
......@@ -122,4 +121,4 @@ bool traverseBVH(const in Mesh mesh, const in Ray local_ray, const in bool use_f
return hit_triangle;
}
#endif //__GL_BVH
#endif //INCLUDE_PATHTRACER_BVH_GLSL
#ifndef __GL_MESH_DATASTRUCTURE
#define __GL_MESH_DATASTRUCTURE
#ifndef INCLUDE_PATHTRACER_DATASTRUCTURE_GLSL
#define INCLUDE_PATHTRACER_DATASTRUCTURE_GLSL
#include <raytracer/datastructure/mesh_bvh.glsl>
//#include <raytracer/datastructure/mesh_angular_linespace.glsl>
#include <raytracer/datastructure/mesh_linespace.glsl>
#include <pathtracer/buffers.glsl>
#include <util/scene/mesh.glsl>
#include <util/tracing/bvh_node.glsl>
uniform bool u_use_ls;
#include <pathtracer/data/mesh_bvh.glsl>
#include <pathtracer/data/mesh_linespace.glsl>
//#include <raytracer/datastructure/mesh_angular_linespace.glsl>
#define USE_OBJECT_BVH true ||
//#define USE_OBJECT_BVH false &&
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);
......@@ -25,17 +25,12 @@ bool intersectsAny(const in Ray ray, const in float max_distance, bool force_bvh
return traverseObjects(ray, true, max_distance, unused_hit, t_min, force_bvh);
}
Bounds getObjectNodeBounds(int index)
{
return b_object_nodes[index].bounds;
}
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)
{
float t = t_min;
float max_dist = max_distance;
// Check once the AABB for the whole scene
bool hit_scene = ray.intersectsBounds(getObjectNodeBounds(0), max_distance);
bool hit_scene = ray.intersectsBounds(global_bvh_nodes_data[0].bounds, max_distance);
bool hit_triangle = false;
int current_node = 0;
......@@ -45,13 +40,13 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
while (hit_scene)
{
if (b_object_nodes[current_node].type == 0) //Inner node.
if (global_bvh_nodes_data[current_node].type == 0) //Inner node.
{
int id_left = int(b_object_nodes[current_node].left_idx);
bool hit_left = ray.intersectsBounds(getObjectNodeBounds(id_left), max_distance);
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_right = int(b_object_nodes[current_node].right_idx);
bool hit_right = ray.intersectsBounds(getObjectNodeBounds(id_right), 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);
//both hit
if (hit_left && hit_right)
......@@ -87,16 +82,16 @@ 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(b_object_nodes[current_node].left_idx);
int end = int(b_object_nodes[current_node].right_idx);
int start = int(global_bvh_nodes_data[current_node].left_idx);
int end = int(global_bvh_nodes_data[current_node].right_idx);
for (int i = start; i <= end; i++)
{
float current_t = t_min;
const Mesh mesh = b_meshes[i];
const Mesh mesh = meshes_data[i];
if(force_bvh)
{
if(mesh.traverseBVH(ray.makeMeshLocal(mesh), use_first, current_t, false, hit, unused, t_min)){
if(mesh.traverseBVH(ray.makeRelative(mesh), use_first, current_t, false, hit, unused, t_min)){
hit_triangle = true;
if (use_first)
{
......@@ -106,7 +101,7 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
}
else
{
if(mesh.traverseLineSpace(ray.makeMeshLocal(mesh), use_first, current_t, hit, t_min)){
if(mesh.traverseLineSpace(ray.makeRelative(mesh), use_first, current_t, hit, t_min)){
hit_triangle = true;
if (use_first)
{
......@@ -127,16 +122,16 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
return hit_triangle;
}
current_node = int(b_object_nodes[current_node].parent);
current_node = int(global_bvh_nodes_data[current_node].parent);
bitstack = bitstack >> 1;
}
//Use other (right) sibling from the left child of the branched tree node.
current_node = int(b_object_nodes[b_object_nodes[current_node].parent].right_idx);
current_node = int(global_bvh_nodes_data[global_bvh_nodes_data[current_node].parent].right_idx);
bitstack = bitstack ^ 1;
}
return hit_triangle;
}
#endif //__GL_MESH_DATASTRUCTURE
#endif //INCLUDE_PATHTRACER_DATASTRUCTURE_GLSL
#ifndef __GL_LINESPACE
#define __GL_LINESPACE
#ifndef INCLUDE_PATHTRACER_LINESPACE_GLSL
#define INCLUDE_PATHTRACER_LINESPACE_GLSL
#include <raytracer/basic_structs.glsl>
#include <raytracer/buffers.glsl>
#include <raytracer/intersections.glsl>
#include <raytracer/std.glsl>
#include <raytracer/utilities.glsl>
#include <util/scene/mesh.glsl>
#include <util/tracing/intersections.glsl>
#include <util/tracing/linespace.glsl>
#include <util/tracing/tracing.glsl>
uint ls__faceRangeIndex(uint in_face, uint out_face)
uint configurationID(uint in_face, uint out_face)
{
return uint((((-0.5f * float(in_face)) + 4.5f)*float(in_face))) - 1u + out_face;
}
const uint c_face_width_axis[3] = {2, 2, 0};
const uint c_face_height_axis[3] = {1, 0, 1};
uint linesBetweenFaces(const in Linespace linespace, uint inface, uint outface)
{
uint axis_in_width = linespace.resolution[c_face_width_axis[inface % 3]];
uint axis_in_height = linespace.resolution[c_face_height_axis[inface % 3]];
uint axis_in_width = linespace.resolution[face_width_axis[inface % 3]];
uint axis_in_height = linespace.resolution[face_height_axis[inface % 3]];
uint axis_out_width = linespace.resolution[c_face_width_axis[outface % 3]];
uint axis_out_height = linespace.resolution[c_face_height_axis[outface % 3]];
uint axis_out_width = linespace.resolution[face_width_axis[outface % 3]];
uint axis_out_height = linespace.resolution[face_height_axis[outface % 3]];
return axis_in_width * axis_in_height * axis_out_width * axis_out_height;
}
......@@ -31,7 +27,7 @@ uint offsetOf(const in Linespace linespace, uint inface, uint outface)
uint offset = 0;
// Caution! Fallthrough switch. Seemed to perform much better than a for-loop, usually even being faster than precalculated offsets in release builds.
switch (ls__faceRangeIndex(inface, outface))
switch (configurationID(inface, outface))
{
case 15:
offset += linesBetweenFaces(linespace, 4, 5);
......@@ -71,36 +67,12 @@ uint offsetOf(const in Linespace linespace, uint inface, uint outface)
return offset;
}
uint getFaceWidth(uint axis){
return c_face_width_axis[axis];
}
uint getFaceHeight(uint axis){
return c_face_height_axis[axis];
}
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
bool flip_indices = face != axis;
return !flip_indices
? uvec2(at_position[getFaceWidth(axis)] / mesh.linespace.patch_size, at_position[getFaceHeight(axis)] / mesh.linespace.patch_size)
: uvec2(mesh.linespace.resolution[getFaceWidth(axis)], mesh.linespace.resolution[getFaceHeight(axis)]) -
uvec2(at_position[getFaceWidth(axis)] / mesh.linespace.patch_size, at_position[getFaceHeight(axis)] / mesh.linespace.patch_size)- 1;
}
float getDistance(const in Ray ray, const in Hit hit, inout uint dir_sign)
{
Mesh mesh = b_meshes[hit.mesh];
Triangle triangle = mesh.triangles[hit.triangle];
Vertex v1 = mesh.vertices[triangle.indices[1]];
Vertex v2 = mesh.vertices[triangle.indices[2]];
Vertex v3 = mesh.vertices[triangle.indices[0]];
vec3 vector = hit__getFromBarycentric(hit.barycentric, triangle, position).xyz - ray.origin;
dir_sign = uint(sign(dot(vector, ray.direction)));
return length(vector);
? uvec2(at_position[face_width_axis[axis]] / mesh.linespace.patch_size, at_position[face_height_axis[axis]] / mesh.linespace.patch_size)
: uvec2(mesh.linespace.resolution[face_width_axis[axis]], mesh.linespace.resolution[face_height_axis[axis]]) -
uvec2(at_position[face_width_axis[axis]] / mesh.linespace.patch_size, at_position[face_height_axis[axis]] / mesh.linespace.patch_size)- 1;
}
struct PatchInfo
......@@ -112,7 +84,7 @@ struct PatchInfo
float t;
};
uint ls__lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax, int face_in, int face_out, inout bool direction_swapped)
uint lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax, int face_in, int face_out, inout bool direction_swapped)
{
Linespace linespace = mesh.linespace;
......@@ -145,9 +117,9 @@ uint ls__lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax,
//Now with all that information, we can retrieve the line index.
uint offset = offsetOf(linespace, entry_info.face, exit_info.face);
uint start_height = linespace.resolution[getFaceHeight(entry_info.axis)];
uint end_width = linespace.resolution[getFaceWidth(exit_info.axis)];
uint end_height = linespace.resolution[getFaceHeight(exit_info.axis)];
uint start_height = linespace.resolution[face_height_axis[entry_info.axis]];
uint end_width = linespace.resolution[face_width_axis[exit_info.axis]];
uint end_height = linespace.resolution[face_height_axis[exit_info.axis]];
uint start = (entry_info.patch_index.y + entry_info.patch_index.x * start_height) * end_width * end_height;
uint end = (exit_info.patch_index.y + exit_info.patch_index.x * end_height);
......@@ -173,7 +145,7 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
bool swapped = false;
uint line_id = ls__lineIndex(offset_ray, mesh, tmin, tmax, face_tmin, face_tmax, swapped);
uint line_id = lineIndex(offset_ray, mesh, tmin, tmax, face_tmin, face_tmax, swapped);
Line line = mesh.linespace.lines[line_id];
int near_data = swapped ? line.farthest : line.nearest;
......@@ -187,8 +159,6 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
if(local_ray.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
{
float nearest_distance = t-offset;
//float nearest_distance = getDistance(offset_ray, nearer, dir_sign)-offset;
if(nearest_distance > 0 && max_distance > nearest_distance){
hit = nearer;
t_min = t;
......@@ -205,7 +175,6 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
nearer.mesh = mesh.id;
if(local_ray.intersectsTrianglePlane(near_data, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
{
//float farthest_distance = getDistance(offset_ray, nearer, dir_sign)-offset;
float farthest_distance = t-offset;
if(farthest_distance > 0 && max_distance > farthest_distance){
......@@ -221,4 +190,4 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
#endif //__GL_LINESPACE
#endif //INCLUDE_PATHTRACER_LINESPACE_GLSL
......@@ -3,15 +3,18 @@
#extension GL_ARB_shading_language_include : require
#extension GL_ARB_compute_variable_group_size : require
#include <raytracer/basic_structs.glsl>
#include <raytracer/datastructure/mesh_datastructure.glsl>
#include <raytracer/buffers.glsl>
#include <raytracer/utilities.glsl>
#include <raytracer/random.glsl>
#include <raytracer/properties/camera.glsl>
#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 struct
{
bool u_random_subpixel; //defaults to false.
......@@ -23,10 +26,11 @@ void resetImportance(int id);
void main()
{
if (!u_render_target.contains(gl_GlobalInvocationID.xy))
ivec2 target_size = u_render_target.imageSize();
if (!(int(gl_GlobalInvocationID.x) < target_size.x && int(gl_GlobalInvocationID.y) < target_size.y))
return;
int id = invocation2D();
int id = u_render_target.imageSize().x * int(gl_GlobalInvocationID.y) + int(gl_GlobalInvocationID.x);
generate(id);
trace(id);
resetImportance(id);
......@@ -34,19 +38,19 @@ void main()
void generate(int id)
{
b_traces[id].ray = u_camera.getRayFromPixel(vec2(gl_GlobalInvocationID.xy), settings.u_random_subpixel ? vec2(0, 0) : rand2D(random_seed + id));
traces_data[id].ray = u_camera.getRayFromPixel(vec2(gl_GlobalInvocationID.xy), settings.u_random_subpixel ? vec2(0, 0) : rand2D(random_seed + id));
}
void trace(int id)
{
b_traces[id].hit.invalidate();
bool intersects = nearestIntersection(b_traces[id].ray, b_traces[id].hit, true);
traces_data[id].hit.invalidate();
bool intersects = nearestIntersection(traces_data[id].ray, traces_data[id].hit, true);
}
void resetImportance(int id)
{
b_traces[id].properties.accuracy_importance = 1.f;
b_traces[id].properties.shadow_importance = 1.f;
b_traces[id].properties.bounce_amount = 0;
b_traces[id].properties.travelled_distance = 0;