Commit 7c90d76f authored by Johannes Braun's avatar Johannes Braun
Browse files

introduced a bidirectional linear-to-normal-hemisphere mapping

parent c75ad0f2
......@@ -6,8 +6,8 @@
<item name="vsync" value="0"/>
<item name="msaa" value="4"/>
</group>
<group name="linespace">
<item name="subdivisions" value="24"/>
</group>
</settings>
\ No newline at end of file
</settings>
<linespace version="1.0">
<item name="subdivisions" value="4"/>
<item name="radial-subdivision" value="12"/>
<item name="generator" value="gpu"/>
</linespace>
......@@ -117,11 +117,16 @@ struct line_hit
int triangle;
};
#define USE_ANGULAR_LS
struct Line
{
// int triangle;
line_hit nearest;
#ifdef USE_ANGULAR_LS
int triangle;
#else
line_hit nearest;
line_hit farthest;
#endif
};
struct Linespace
......@@ -153,9 +158,9 @@ struct Mesh
struct TraceProperties
{
float accuracy_importance;
float accuracy_importance;
float shadow_importance;
uint bounce_amount;
float travelled_distance;
};
......@@ -164,7 +169,7 @@ struct Trace
{
Ray ray;
Hit hit;
//Additional properties for BVH-LS-Hybrid
TraceProperties properties;
};
......@@ -198,4 +203,4 @@ struct UIntRange
uint max;
};
#endif //__GL_BASIC_STRUCTS
\ No newline at end of file
#endif //__GL_BASIC_STRUCTS
......@@ -12,7 +12,7 @@ const uint face_height_axis[3] = {1, 0, 1};
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
bool flip_indices = face != axis;
return !flip_indices
return !flip_indices
? 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;
......@@ -26,11 +26,11 @@ float getDistance(const in Ray ray, const in Hit hit, inout uint dir_sign)
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);
}
......@@ -43,74 +43,88 @@ struct PatchInfo
float t;
};
const uint m_radial_subdivisions = 1; //TODO: put into ssbo
const uint m_radial_subdivisions = 12; //TODO: put into ssbo
uint id_from_direction(vec3 direction, uint quarter_subdivision, uint axis_up, uint axis_horizontal, uint axis_vertical)
{
//save some results
float half_circular_subdivision = 2.f * float(quarter_subdivision) * ONE_OVER_PI;
float up = direction[axis_up];
uint row = uint(round(half_circular_subdivision * asin(up))) - 1;
if (row >= quarter_subdivision - 1) {
//I'll return here because there might be some issues with normalizing a near-zero planar direction later on.
return 4 * quarter_subdivision * (quarter_subdivision - 1);
}
vec2 planar_direction = normalize(vec2(direction[axis_horizontal], direction[axis_vertical]));
int id_x = int(round(half_circular_subdivision * asin(planar_direction.x)));
//goes from 0->0 to r/2->r/2 and counts down afterwards.
int id_y = int(round(half_circular_subdivision * acos(planar_direction.y)));
return int(4 * quarter_subdivision*row) + (id_x >= 0 ? id_y : (4 * int(quarter_subdivision) - id_y));
}
uint lineIndex(const in Ray ray, const in Mesh mesh, float t, int face, bool reverse)
{
const Linespace linespace = mesh.linespace;
{
const Linespace linespace = mesh.linespace;
vec3 direction = reverse ? -ray.direction : ray.direction;
uint dir_id = id_from_direction(direction, m_radial_subdivisions, face % 3, face_width_axis[face % 3], face_width_axis[face % 3]);
const uint per_patch = 4 * m_radial_subdivisions * (m_radial_subdivisions-1) + 1;
vec3 horizontal = vec3(0);
horizontal[face_width_axis[face % 3]] = face >= 2 ? -1 : 1;
vec3 vertical = vec3(0);
vertical[face_width_axis[face % 3]] = face >= 2 ? -1 : 1;
vec3 direction = reverse ? -ray.direction : ray.direction;
float radial_x = dot(horizontal, direction);
float radial_y = dot(vertical, direction);
const uvec2 entry_patch = getPatch(mesh, ray.origin + t * ray.direction - linespace.bounds.min.xyz, face % 3, face);
const uint n = uint(face);
const uint n = uint(max(int(face)-1, 0));
uint patch_offset = uint(n % 3 >= 1) * (linespace.resolution[face_width_axis[0]] + (uint(n % 3 >= 2) * linespace.resolution[face_width_axis[1]])) * linespace.resolution[face_height_axis[0]];
patch_offset += uint((n / 3) * dot(linespace.resolution.zzx, linespace.resolution.yxy));
const uint radial_diameter = 2 * m_radial_subdivisions - 1;
const uint square_radial_diameter = radial_diameter * radial_diameter;
const uint patch_sub_offset = linespace.resolution[face_width_axis[uint(face) % 3]] * entry_patch.y + entry_patch.x;
radial_x += 1;
radial_x *= float(m_radial_subdivisions) + 1;
radial_x -= 1;
radial_y += 1;
radial_y *= float(m_radial_subdivisions) + 1;
radial_y -= 1;
return patch_offset * square_radial_diameter + patch_sub_offset + uint(radial_y) * radial_diameter + uint(radial_x);
return patch_offset * per_patch + patch_sub_offset * per_patch + dir_id;
}
bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min)
{
{
float tmin;
float tmax;
int face_tmin;
int face_tmax;
float offset = 1e-5;//1000;//mesh.linespace.patch_size;
float offset = mesh.linespace.patch_size;
Ray offset_ray = local_ray;
offset_ray.origin += local_ray.direction * offset;
if(!offset_ray.intersectsBounds(mesh.linespace.bounds, tmin, tmax, face_tmin, face_tmax) || t_min <= tmin-offset || tmin-offset > max_distance)
{
return false;
}
uint line_id = lineIndex(offset_ray, mesh, tmin, face_tmin, false);
Line near_data = mesh.lines[line_id];
uint line_id = lineIndex(offset_ray, mesh, tmin, face_tmin, false);
Line near_data = mesh.linespace.lines[line_id];
Hit nearer;
float t;
if(near_data.triangle != -1)
if(near_data.triangle != -1)
{
nearer.triangle = near_data.triangle;
nearer.mesh = mesh.id;
if(local_ray.intersectsTrianglePlane(near_data.triangle, mesh, t, nearer.barycentric.x, nearer.barycentric.y))
{
float nearest_distance = t-offset;
if(nearest_distance > 0 && max_distance > nearest_distance){
hit = nearer;
t_min = t;
......@@ -119,10 +133,10 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
}
}
line_id = lineIndex(offset_ray, mesh, tmax, face_tmax, true);
near_data = mesh.lines[line_id];
if(near_data.triangle != -1)
near_data = mesh.linespace.lines[line_id];
if(near_data.triangle != -1)
{
nearer.triangle = near_data.triangle;
nearer.mesh = mesh.id;
......@@ -138,9 +152,9 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
}
}
return false;
}
#endif //__GL_LINESPACE
\ No newline at end of file
#endif //__GL_LINESPACE
......@@ -2,7 +2,8 @@
#define __GL_MESH_DATASTRUCTURE
#include <raytracer/datastructure/mesh_bvh.glh>
#include <raytracer/datastructure/mesh_linespace.glh>
#include <raytracer/datastructure/mesh_angular_linespace.glh>
//#include <raytracer/datastructure/mesh_linespace.glh>
uniform bool u_use_ls;
......@@ -39,7 +40,7 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
int current_node = 0;
int bitstack = 0;
Hit unused;
while (hit_scene)
......@@ -55,7 +56,7 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
//both hit
if (hit_left && hit_right)
{
// shift bitstack and mark as branched, so we can use the marker
// shift bitstack and mark as branched, so we can use the marker
// when backtracking to stop here and use the right child.
bitstack = bitstack << 1;
current_node = id_left;
......@@ -88,7 +89,7 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
int start = int(b_object_nodes[current_node].left_idx);
int end = int(b_object_nodes[current_node].right_idx);
for (int i = start; i <= end; i++)
{
float current_t = t_min;
......@@ -138,4 +139,4 @@ bool traverseObjects(const in Ray ray, const in bool use_first, const in float m
return hit_triangle;
}
#endif //__GL_MESH_DATASTRUCTURE
\ No newline at end of file
#endif //__GL_MESH_DATASTRUCTURE
......@@ -40,7 +40,7 @@ uint getFaceHeight(uint axis){
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
bool flip_indices = face != axis;
return !flip_indices
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;
......@@ -54,11 +54,11 @@ float getDistance(const in Ray ray, const in Hit hit, inout uint dir_sign)
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);
}
......@@ -72,9 +72,9 @@ struct PatchInfo
};
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)
{
{
Linespace linespace = mesh.linespace;
PatchInfo entry_info;
PatchInfo exit_info;
......@@ -89,7 +89,7 @@ uint ls__lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax,
exit_info.face = direction_swapped ? face_in : face_out;
/////////////////////////////////////////////////////////////
//calculate entry and exit points on the minimum-normalized bounding box
//calculate entry and exit points on the minimum-normalized bounding box
//(so that bounds.min is at (0,0,0) and bounds.max is at the former bounding box's size)
entry_info.position = ray.origin + entry_info.t * ray.direction - linespace.bounds.min.xyz;
exit_info.position = ray.origin + exit_info.t * ray.direction - linespace.bounds.min.xyz;
......@@ -100,7 +100,7 @@ uint ls__lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax,
// getPatch mirrors the patches on the negative axises per definition.
entry_info.patch_index = getPatch(mesh, entry_info.position, entry_info.axis, entry_info.face);
exit_info.patch_index = getPatch(mesh, exit_info.position, exit_info.axis, exit_info.face);
//Now with all that information, we can retrieve the line index.
uint offset = offsetof(linespace, ls__faceRangeIndex(entry_info.face, exit_info.face));
......@@ -110,36 +110,36 @@ uint ls__lineIndex(const in Ray ray, const in Mesh mesh, float tmin, float tmax,
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);
return offset + start + end;
}
bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool use_first, const in float max_distance, inout Hit hit, inout float t_min)
{
{
float tmin;
float tmax;
int face_tmin;
int face_tmax;
float offset = 1e-5;//1000;//mesh.linespace.patch_size;
float offset = mesh.linespace.patch_size;//1;//e-2;//1000;//mesh.linespace.patch_size;
Ray offset_ray = local_ray;
offset_ray.origin += local_ray.direction * offset;
if(!offset_ray.intersectsBounds(mesh.linespace.bounds, tmin, tmax, face_tmin, face_tmax) || t_min <= tmin-offset || tmin-offset > max_distance)
{
return false;
}
bool swapped = false;
uint line_id = ls__lineIndex(offset_ray, mesh, tmin, tmax, face_tmin, face_tmax, swapped);
Line line = mesh.linespace.lines[line_id];
line_hit near_data = swapped ? line.farthest : line.nearest;
Hit nearer;
float t;
if(near_data.triangle != -1)
if(near_data.triangle != -1)
{
nearer.triangle = near_data.triangle;
nearer.mesh = mesh.id;
......@@ -147,7 +147,7 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
{
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;
......@@ -156,9 +156,9 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
}
}
near_data = swapped ? line.nearest : line.farthest;
if(near_data.triangle != -1)
if(near_data.triangle != -1)
{
nearer.triangle = near_data.triangle;
nearer.mesh = mesh.id;
......@@ -175,9 +175,9 @@ bool traverseLineSpace(const in Mesh mesh, const in Ray local_ray, const in bool
}
}
}
return false;
}
#endif //__GL_LINESPACE
\ No newline at end of file
#endif //__GL_LINESPACE
#include <util/integers.h>
#include <glm/glm.hpp>
#include <glm/ext.hpp>
constexpr unsigned radial_subdivision = 3;
glm::vec3 direction(unsigned id)
{
//start at the second row. The first one will be flat against the patch plane and won't hit anything anyways.
unsigned row = id / (4 * radial_subdivision) + 1;
float row_pi_2_subdiv = row * glm::pi<float>() / (2.f * radial_subdivision);
float up = glm::sin(row_pi_2_subdiv);
float plane_scale = glm::cos(row_pi_2_subdiv);
float id_pi_2_subdiv = id * glm::pi<float>() / (2.f * radial_subdivision);
float x = glm::sin(id_pi_2_subdiv);
float y = glm::cos(id_pi_2_subdiv);
glm::vec2 scaled(x, y);
scaled *= plane_scale;
glm::vec3 direction;
//this is "up"
direction[1] = up;
//this is "horizontal"
direction[0] = scaled.x;
//this is "vertical"
direction[2] = scaled.y;
return direction;
}
unsigned last()
{
return ;
}
unsigned id(glm::vec3 direction)
{
glm::vec3 normal(0, 1, 0);
glm::vec3 horz(1, 0, 0);
glm::vec3 vert(0, 0, 1);
float up = glm::dot(normal, direction);
unsigned row = unsigned(glm::round((2.f * radial_subdivision) * glm::asin(up) / glm::pi<float>())) - 1;
if (row >= radial_subdivision - 1) {
//I'll return here because there might be some issues with normalizing a near-zero planar direction later on.
return 4 * radial_subdivision * (radial_subdivision - 1);
}
glm::vec2 planar_direction = glm::normalize(glm::vec2(glm::dot(horz, direction), glm::dot(vert, direction)));
int id_x = unsigned(glm::round((2.f * radial_subdivision) * (glm::asin(planar_direction.x) / glm::pi<float>())));
//goes from 0->0 to r/2->r/2 and counts down afterwards.
int id_y = unsigned(glm::round((2.f * radial_subdivision) * (glm::acos(planar_direction.y) / glm::pi<float>())));
return 4 * radial_subdivision*row + (id_x >= 0 ? id_y : (4 * radial_subdivision - id_y));
}
int main(int argc, char* argv[])
{
unsigned i = integers::bits(0b100101110);
auto dir0sdf = direction(0);
auto dir1553 = direction(1);
auto dirbggea = direction(2);
auto dir0ah = direction(3);
auto dir1htz53 = direction(4);
auto dirbu57 = direction(5);
auto dir0aag = direction(6);
auto dir1afg53 = direction(7);
auto dirb = direction(8);
auto dir0 = direction(9);
auto dir1gs53 = direction(10);
auto dirgsb = direction(11);
auto dir2sw35 = direction(16);
auto dir2ss35 = direction(22);
auto dir2s35 = direction(24);
auto aidi = id(dir0sdf);
auto aidi314 = id(dir1553);
auto aidi4214 = id(dirbggea);
auto aidi2903 = id(dir0ah);
auto atdiq = id(dir1htz53);
auto aidi3t3a414 = id(dirbu57);
auto aidi634afa214 = id(dir0aag);
auto aidiaaaaaf2903 = id(dir1afg53);
auto atdiasf = id(dirb);
auto aidi3t3ff414 = id(dir0);
auto aidi6342aa14 = id(dir1gs53);
auto aidiaaa290ayy3 = id(dirgsb);
auto aidiawwtwy3 = id(dir2sw35);
auto aidiaaappy3 = id(dir2ss35);
auto aidiaaasdyy3 = id(dir2s35);
return 0;
}
\ No newline at end of file
......@@ -93,6 +93,7 @@ namespace glare
}
}
});
al::listenerf(al::ListenerParam::eGain, 0.02f);
core::SplashScreen splash_screen(files::asset("/preferences/splash_01.xml"));
splash_screen.run();
......@@ -127,6 +128,7 @@ namespace glare
environment_source->setLooping(true);
environment_source->play();
const auto &coll = *m_collector->getUnit<raytrace::MeshCollector>("mesh_collector").localCollectors().begin()->second;
//const advanced::AngularLinespace lisp(coll, 100, 16);
......
......@@ -259,7 +259,7 @@ namespace glare
const int largest_axis = bounds.largest();
const glm::vec3 bounds_size = glm::max(glm::vec3(bounds.size().xyz), glm::vec3(1e-5f));
const float largest_axis_value = glm::compMax(bounds_size);
this->size = largest_axis_value / float(max_subdivisions);
this->size = largest_axis_value / float(max_subdivisions) + 1e-5f;
Please register or sign in to reply
resolution = glm::ivec3(0);
resolution[largest_axis] = max_subdivisions;
......
......@@ -5,6 +5,8 @@
// --------------- EXTERN ---------------
#include <engine/Time.h>
#include <pugixml/pugixml.hpp>
#include <util/hemisphere1d.h>
// --------------- INTERN ---------------
......@@ -12,17 +14,40 @@ namespace glare
{
namespace raytrace
{
AngularLinespace::AngularLinespace()
{
}
AngularLinespace::AngularLinespace(const LocalCollector &collector, int box_subdivisions, int radial_subdivisions, Platform generator)
: AngularLinespace()
{
generate(collector, box_subdivisions, radial_subdivisions, generator);
}
void AngularLinespace::generate(const LocalCollector &collector, const fs::path &settings_file)
{
pugi::xml_document doc;
Log_Warn << doc.load_file(files::asset("/preferences/linespace_default.xml").c_str()).description();
const auto& linespace_tag = doc.child("linespace");
const int max_subdivisions = linespace_tag.find_child_by_attribute("item", "name", "subdivisions").attribute("value").as_int(16);
const int radial_subdivisions = linespace_tag.find_child_by_attribute("item", "name", "radial-subdivision").attribute("value").as_int(16);
const std::string gen = linespace_tag.find_child_by_attribute("item", "name", "generator").attribute("value").as_string("cpu");
Platform generator = gen == "gpu" ? Platform::eGPU : Platform::eCPU;
generate(collector, max_subdivisions, radial_subdivisions, generator);
}
void AngularLinespace::generate(const LocalCollector &collector, int box_subdivisions, int radial_subdivisions, Platform generator)
{
core::ClockMS clock;
m_subdivision = math::bounds_subdivision_t(collector.bounds(), box_subdivisions);
m_radial_subdivisions = radial_subdivisions;
m_lines_per_patch = linesPerPatch();
m_generator = generator;
m_num_lines = unsigned(calculateLineCount());
......@@ -35,40 +60,30 @@ namespace glare
const LocalBVH &line_bvh = collector.bvh();
for (Face face = Face::ePosX; unsigned(face) <= unsigned(Face::eNegZ); face = Face(unsigned(face) + 1))
{
const unsigned count = m_subdivision.resolution[face_width_axises[unsigned(face) % 3]] * m_subdivision.resolution[face_height_axises[unsigned(face) % 3]];
const unsigned patches = m_subdivision.resolution[face_width_axises[unsigned(face) % 3]] * m_subdivision.resolution[face_height_axises[unsigned(face) % 3]];
Log_Info << "Starting at " << unsigned(face);
const unsigned radial_diameter = 2 * radial_subdivisions - 1;
const unsigned count_and_radial = count * radial_diameter * radial_diameter;
const unsigned count_and_radial = patches * m_lines_per_patch;
Log_Info << "COUNT patches " << patches;
Log_Info << "COUNT lpp " << m_lines_per_patch;
Log_Info << "COUNT at " << count_and_radial;
#pragma omp parallel for schedule(dynamic)
for (int gid = 0; gid < int(count_and_radial); ++gid)
{
const unsigned width = m_subdivision.resolution[face_width_axises[unsigned(face) % 3]];
const unsigned id = gid / (radial_diameter * radial_diameter);
const unsigned radial_id = gid % (radial_diameter * radial_diameter);
const unsigned id = gid / m_lines_per_patch;
const unsigned radial_id = gid % m_lines_per_patch;
patch_t patch(face);
patch.index_horizontal = id % width;
patch.index_vertical = id / width;
const unsigned radial_x = radial_id % radial_diameter;
const unsigned radial_y = radial_id / radial_diameter;