Commit f4847c16 authored by unknown's avatar unknown
Browse files

LS now works a bit better.

parent 64e2e385
......@@ -24,7 +24,7 @@ bool intersectsRayBounds(const in Ray ray, const in Bounds bounds)
}
int faceID(float t, float t1, float t2, float t3, float t4, float t5, float t6) {
return t == t1 ? 3 : (t == t2 ? 0 : (t == t3 ? 4 : (t == t4 ? 2 : (t == t5 ? 5 : 3))));
return t == t1 ? 3 : (t == t2 ? 0 : (t == t3 ? 4 : (t == t4 ? 1 : (t == t5 ? 5 : 2))));
}
bool intersectsRayBounds(const in Ray ray, const in Bounds bounds, inout float tmin, inout float tmax, inout int face_tmin, inout int face_tmax)
......
......@@ -5,6 +5,7 @@
#include <raytracer/buffers.glh>
#include <raytracer/intersections.glh>
#include <raytracer/std.glh>
#include <raytracer/utilities.glh>
const uvec3 c_face_width_axises = { 2, 2, 0 };
const uvec3 c_face_height_axises = { 1, 0, 1 };
......@@ -14,48 +15,81 @@ uint faceRangeIndex(uint in_face, uint out_face)
return uint((((-0.5f * in_face) + 4.5f)*in_face) - 1u + out_face);
}
const uint offsets[15] = { 0, 56644, 125426, 182070, 238714, 307496, 376278, 432922, 489566, 558348, 627130, 695912, 779433, 836077, 904859 };
uvec2 getPatch(const in Mesh mesh, vec3 at_position, int axis, int face){
bool flip_indices = face>2;
return uvec2(
flip_indices ? (mesh.linespace.resolution[c_face_width_axises[axis]] - (at_position[c_face_width_axises[axis]] / mesh.linespace.patch_size)) : (at_position[c_face_width_axises[axis]] / mesh.linespace.patch_size),
flip_indices ? (mesh.linespace.resolution[c_face_height_axises[axis]] - (at_position[c_face_height_axises[axis]] / mesh.linespace.patch_size)) : (at_position[c_face_height_axises[axis]] / mesh.linespace.patch_size)
);
}
struct PatchInfo
{
int face;
int axis;
uvec2 patch_index;
vec3 position;
float t;
};
float getDistance(const in Ray ray, const in Hit hit)
{
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]];
return length(hit__getFromBarycentric(hit.barycentric, triangle, position).xyz - ray.origin);
}
bool getLineIndex(const in Ray ray, const in Mesh mesh, inout uint line_id, inout bool direction_swapped)
{
float tmin, tmax;
int face_in, face_out;
direction_swapped = false;
//If the AABB is not intersected, cancel the traversal.
if (!intersectsRayBounds(ray, mesh.linespace.bounds, tmin, tmax, face_in, face_out))
return false;
if (face_in < face_out) {
float tmp_t = tmin;
tmin = tmax;
tmax = tmp_t;
int tmp_face = face_in;
face_in = face_out;
face_out = tmp_face;
direction_swapped = true;
}
// face_in > face_out is an unsupported configuration for reasons of generation performance and memory conservation.
// If that happens, flip tmin, tmax and the two faces accordingly and mark it as flipped to we can take the farthest intersection in the shaft instead of the nearest.
direction_swapped = face_in > face_out;
PatchInfo entry_info;
PatchInfo exit_info;
entry_info.t = direction_swapped ? tmax : tmin;
exit_info.t = direction_swapped ? tmin : tmax;
entry_info.face = direction_swapped ? face_out : face_in;
exit_info.face = direction_swapped ? face_in : face_out;
vec3 entry_point = ray.origin + tmin * ray.direction - mesh.linespace.bounds.min.xyz;
vec3 exit_point = ray.origin + tmax * ray.direction - mesh.linespace.bounds.min.xyz;
//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 - mesh.linespace.bounds.min.xyz;
exit_info.position = ray.origin + exit_info.t * ray.direction - mesh.linespace.bounds.min.xyz;
int in_axis = face_in % 3;
int out_axis = face_out % 3;
entry_info.axis = entry_info.face % 3;
exit_info.axis = exit_info.face % 3;
//TODO check if neg faces should be mirrored somehow
uvec2 patch_in = uvec2(c_face_width_axises[in_axis], c_face_height_axises[in_axis]);
uvec2 patch_out = uvec2(c_face_width_axises[out_axis], c_face_height_axises[out_axis]);
uint offset_index = faceRangeIndex(face_in, face_out);
uint offset = offsets[offset_index];
uint start_height = mesh.linespace.resolution[c_face_height_axises[in_axis]];
uint end_width = mesh.linespace.resolution[c_face_width_axises[out_axis]];
uint end_height = mesh.linespace.resolution[c_face_height_axises[out_axis]];
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);
uint offset_index = faceRangeIndex(entry_info.face, exit_info.face);
uint offset = mesh.offsets[offset_index];
uint start_height = mesh.linespace.resolution[c_face_height_axises[entry_info.axis]];
uint end_width = mesh.linespace.resolution[c_face_width_axises[exit_info.axis]];
uint end_height = mesh.linespace.resolution[c_face_height_axises[exit_info.axis]];
uint start = (patch_in.y + patch_in.x * start_height) * end_width * end_height;
uint end = (patch_out.y + patch_out.x * end_height);
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);
line_id = offset + start + end;
......@@ -64,13 +98,14 @@ bool getLineIndex(const in Ray ray, const in Mesh mesh, inout uint line_id, inou
bool linespace__traverse(const in uint mesh_id, const in Ray ray, inout Hit hit) {
Mesh mesh = b_meshes[mesh_id];
//For ease of use, substitute Ray<->OBB for Ray<->AABB by transforming the ray into object space.
Ray ray_in = ray;
ray_in.direction = normalize(mat3(mesh.inverse_transformation) * ray_in.direction.xyz);
// TODO: Add a distance check.
ray_in.origin = (mesh.inverse_transformation * vec4(ray_in.origin.xyz, 1)).xyz;
//hit = mesh.linespace.lines[500].nearest;
uint line_id;
bool direction_swapped;
if (!getLineIndex(ray_in, mesh, line_id, direction_swapped))
......@@ -80,35 +115,14 @@ bool linespace__traverse(const in uint mesh_id, const in Ray ray, inout Hit hit)
else
{
Line line = mesh.lines[line_id];
hit = line.nearest;
//hit.barycentric = vec2(1, 0);
//hit.triangle = 0;
hit = direction_swapped ? line.farthest : line.nearest;
hit.mesh = mesh_id;
//Found an intersected shaft. But we don't yet know whether it contains geometry, so look it up as a last step.
return hit.barycentric.x != -1;
}
/*hit.mesh = mesh_id;
hit.triangle = 0;
uint line_index = getLineIndex(ray_in, mesh);
if (intersectsRayBounds(ray_in, mesh.linespace.bounds, FLT_MAX)) {
hit.barycentric = vec2(1, 0);
return true;
}
return false;*/
//return intersectsRayBounds(ray_in, mesh.linespace.bounds, FLT_MAX);
}
Bounds getNodeBounds(int index, const in Mesh mesh)
{
return mesh.nodes[index].bounds;
......@@ -228,9 +242,13 @@ bool traverse(const in uint mesh_id, const in Ray ray, inout Hit hit, const in b
return hit_triangle;
}
#define USE_LS
bool bvh__nearestIntersection(const in Ray ray, inout Hit hit)
{
//return linespace__traverse(0, ray, hit);
#ifdef USE_LS
return linespace__traverse(0, ray, hit);
#endif
//bool hits = false;
//for (int i = 0; i < b_meshes.length(); ++i)
//{
......@@ -254,7 +272,13 @@ bool bvh__nearestIntersection(const in Ray ray, inout Hit hit)
bool bvh__intersectsAny(const in Ray ray, const in float max_distance)
{
//
Hit unused_hit;
#ifdef USE_LS
return false;
return linespace__traverse(0, ray, unused_hit);
#endif
//for (int i = 0; i < b_meshes.length(); ++i)
......@@ -264,8 +288,6 @@ bool bvh__intersectsAny(const in Ray ray, const in float max_distance)
// //current_t = min_t;
//}
//return false;
Hit unused_hit;
float current_t = max_distance;
for (int i = 0; i < b_meshes.length(); ++i)
{
......
......@@ -48,7 +48,7 @@ namespace glare
//Create a skybox from cube map.
m_skybox = std::make_shared<core::Skybox>(core::Skybox::collectFilesFrom(core::asset("/textures/ryfjallet/")));
initializeScene(m_current_scene_root / "bunny.dae", 1.f);
initializeScene(m_current_scene_root / "monkey.dae", 1.f);
initializeRenderRequirements();
initializeAdvanced();
initializeGUI();
......@@ -261,9 +261,13 @@ namespace glare
if (collector_active != m_collector->isActive())
m_collector->setActive(collector_active);
if (ImGui::Button("Save Render"))
if (ImGui::Button("Save Render as HDR"))
{
m_raytracer->saveRender(core::asset("/screenshots/render.hdr"));
m_raytracer->saveRenderHDR(core::asset("/screenshots/render.hdr"));
}
if (ImGui::Button("Save Render as PNG"))
{
m_raytracer->saveRender(core::asset("/screenshots/render.png"));
}
ImGui::Separator();
......
......@@ -105,11 +105,16 @@ namespace glare
return *m_render_target;
}
void Raytracer::saveRender(fs::path target) const
void Raytracer::saveRenderHDR(fs::path target) const
{
io::ImageUtilities::saveTexture(target, *m_render_target);
}
void Raytracer::saveRender(fs::path target) const
{
io::ImageUtilities::saveTextureForceUChar(target, *m_render_target);
}
void Raytracer::setGenerator(std::shared_ptr<RayGeneratorBase> generator)
{
m_ray_generator = generator;
......
......@@ -26,6 +26,7 @@ namespace glare
~Raytracer();
const core::TextureRGBA_32F &render(uint32_t width, uint32_t height);
void saveRenderHDR(fs::path target) const;
void saveRender(fs::path target) const;
//template<typename DataStruct>
......
......@@ -169,11 +169,41 @@ namespace glare
flipImage(int(data.width()), int(data.height()), int(data.components()), data.data());
}
template<typename TextureData_t>
static inline void saveDataForceUChar(fs::path path, TextureData_t &data)
{
flipImage(int(data.width()), int(data.height()), int(data.components()), data.data());
if (TextureData_t::gl_type == gl::Type::eFloat) {
//convert from float to uchar
std::vector<unsigned char> converted_data(data.width()*data.height()*data.components());
for (int i = 0; i < converted_data.size(); ++i) {
converted_data[i] = unsigned char(data.data()[i] * 255);
if (i % 4 == 3)
converted_data[i] = 255;
}
saveRawImage(path, int(data.width()), int(data.height()), int(data.components()), converted_data.data());
}
else
{
saveRawImage(path, int(data.width()), int(data.height()), int(data.components()), data.data());
}
flipImage(int(data.width()), int(data.height()), int(data.components()), data.data());
}
template<typename Texture_t>
static inline void saveTexture(fs::path path, Texture_t &data)
{
saveData(path, core::TextureData<Texture_t::gl_format, Texture_t::gl_internal_format, Texture_t::gl_type>(data));
}
template<typename Texture_t>
static inline void saveTextureForceUChar(fs::path path, Texture_t &data)
{
saveDataForceUChar(path, core::TextureData<Texture_t::gl_format, Texture_t::gl_internal_format, Texture_t::gl_type>(data));
}
};
}
}
......
#include "LineSpace.h"
#include <engine/Time.h>
#include <omp.h>
namespace glare
{
namespace ls
{
namespace utilities
#include "LineSpace.h"
#include <engine/Time.h>
#include <omp.h>
namespace glare
{
namespace ls
{
namespace utilities
{
unsigned faceAxis(Face face)
{
......@@ -16,33 +16,33 @@ namespace glare
size_t faceRangeIndex(Face in, Face out)
{
return size_t((((-0.5 * unsigned(in)) + 4.5)*unsigned(in)) - 1 + unsigned(out));
}
unsigned goodSubdivision(size_t polygon_count, glm::vec3 bounds_size)
{
return unsigned(glm::ceil(glm::log2(glm::max(size_t(2), polygon_count)) * glm::log(log2((glm::compMax(bounds_size) / glm::compMin(bounds_size)) + 2 * glm::e<float>()))));
}
}
LineSpace::LineSpace()
{
}
LineSpace::LineSpace(const advanced::LocalCollector &collector, int max_subdivisions)
: LineSpace()
{
generate(collector, max_subdivisions);
}
LineSpace::~LineSpace() {}
void LineSpace::generate(const advanced::LocalCollector &collector, int max_subdivisions)
{
if (max_subdivisions <= 0) {
max_subdivisions = utilities::goodSubdivision(collector.triangles().size(), collector.bounds().size().xyz);
}
}
unsigned goodSubdivision(size_t polygon_count, glm::vec3 bounds_size)
{
return 2*unsigned(glm::ceil(glm::log2(glm::max(size_t(2), polygon_count)) * glm::log(log2((glm::compMax(bounds_size) / glm::compMin(bounds_size)) + 2 * glm::e<float>()))));
}
}
LineSpace::LineSpace()
{
}
LineSpace::LineSpace(const advanced::LocalCollector &collector, int max_subdivisions)
: LineSpace()
{
generate(collector, max_subdivisions);
}
LineSpace::~LineSpace() {}
void LineSpace::generate(const advanced::LocalCollector &collector, int max_subdivisions)
{
if (max_subdivisions <= 0) {
max_subdivisions = utilities::goodSubdivision(collector.triangles().size(), collector.bounds().size().xyz);
}
m_subdivision = math::UniformBoundsSubdivision(collector.bounds(), max_subdivisions);
m_bounds = collector.bounds();
m_bounds.max = m_bounds.min + glm::vec4(m_subdivision.size * glm::vec3(m_subdivision.subdivisions), 0);
......@@ -67,8 +67,8 @@ namespace glare
for (int config = 0; config < 15; ++config) {
Patch begin = c_start_end_patches[config].first;
Patch end = c_start_end_patches[config].second;
#pragma omp critical
#pragma omp critical
{
Log_Info << "Working on lines between Faces " << unsigned(begin.face) << " and " << unsigned(end.face) << "...";
}
......@@ -96,8 +96,8 @@ namespace glare
line_bvh.nearestAndFarthestIntersection(ray, line.nearest, line.farthest);
}
}
}
}
m_line_buffer.setData(m_lines, gl::BufferUsage::eDynamicRead);
m_line_buffer.makeResident(gl::Access::eReadOnly);
......@@ -106,9 +106,9 @@ namespace glare
Log_Info << "[Linespace Data] Memory: " << (m_lines.size() * sizeof(Line)) << " Bytes";
Log_Info << "[Linespace Data] Patch Subdivisions: " << m_subdivision.subdivisions.x << ", " << m_subdivision.subdivisions.y << ", " << m_subdivision.subdivisions.z;
Log_Info << "[Linespace Data] Patch Size: " << m_subdivision.size;
Log_Info << "[Linespace Data] Object Bounds: " << collector.bounds();
}
Log_Info << "[Linespace Data] Object Bounds: " << collector.bounds();
}
void LineSpace::calculateOffsets()
{
size_t current_offset = 0;
......@@ -121,8 +121,8 @@ namespace glare
current_offset += linesBetweenFaces(start, end);
}
}
}
glm::vec3 LineSpace::patchCenter(const Patch &patch)
{
unsigned face_index = unsigned(patch.face);
......@@ -183,60 +183,60 @@ namespace glare
+ (m_subdivision.subdivisions.y * m_subdivision.subdivisions.z * 2 * (m_subdivision.subdivisions.x*m_subdivision.subdivisions.z + m_subdivision.subdivisions.x*m_subdivision.subdivisions.y))
+ m_subdivision.subdivisions.y * m_subdivision.subdivisions.z * m_subdivision.subdivisions.y * m_subdivision.subdivisions.z);
}
const core::Buffer<gl::BufferType::eShaderStorage> &LineSpace::lineBuffer() const
{
return m_line_buffer;
}
const std::vector<Line> &LineSpace::lines() const
{
return m_lines;
}
const math::Bounds &LineSpace::bounds() const
{
return m_bounds;
}
const math::UniformBoundsSubdivision &LineSpace::subdivisions() const
{
return m_subdivision;
}
const std::array<size_t, 15> &LineSpace::offsets() const
{
return m_offsets;
}
LineSpaceRenderer::LineSpaceRenderer(const advanced::SceneCollector &collector, const LineSpace &linespace)
: m_linespace(linespace), m_collector(collector)
{
std::vector<std::shared_ptr<core::Shader>> shaders = {
std::make_shared<core::Shader>(gl::ShaderType::eVertex, "/linespace/visualize/lines.vert"),
std::make_shared<core::Shader>(gl::ShaderType::eGeometry, "/linespace/visualize/lines.geom"),
std::make_shared<core::Shader>(gl::ShaderType::eFragment, "/linespace/visualize/lines.frag")
};
m_program = std::make_unique<core::ShaderProgram>(shaders);
m_vertex_array = std::make_unique<core::VertexArray>();
}
LineSpaceRenderer::~LineSpaceRenderer()
{
}
void LineSpaceRenderer::draw() const
{
}
const core::Buffer<gl::BufferType::eShaderStorage> &LineSpace::lineBuffer() const
{
return m_line_buffer;
}
const std::vector<Line> &LineSpace::lines() const
{
return m_lines;
}
const math::Bounds &LineSpace::bounds() const
{
return m_bounds;
}
const math::UniformBoundsSubdivision &LineSpace::subdivisions() const
{
return m_subdivision;
}
const std::array<size_t, 15> &LineSpace::offsets() const
{
return m_offsets;
}
LineSpaceRenderer::LineSpaceRenderer(const advanced::SceneCollector &collector, const LineSpace &linespace)
: m_linespace(linespace), m_collector(collector)
{
std::vector<std::shared_ptr<core::Shader>> shaders = {
std::make_shared<core::Shader>(gl::ShaderType::eVertex, "/linespace/visualize/lines.vert"),
std::make_shared<core::Shader>(gl::ShaderType::eGeometry, "/linespace/visualize/lines.geom"),
std::make_shared<core::Shader>(gl::ShaderType::eFragment, "/linespace/visualize/lines.frag")
};
m_program = std::make_unique<core::ShaderProgram>(shaders);
m_vertex_array = std::make_unique<core::VertexArray>();
}
LineSpaceRenderer::~LineSpaceRenderer()
{
}
void LineSpaceRenderer::draw() const
{
m_program->use();
m_program->updateStorageBuffer("mesh_buffer", m_collector.meshBuffer());
m_program->updateStorageBuffer("line_buffer", m_linespace.lineBuffer());
m_program->updateUniformUInt("u_mesh", unsigned(m_linespace.m_mesh_id));
m_program->updateUniformUInt("u_triangle_count", unsigned(m_collector.meshCollectors().at(m_linespace.m_mesh_id)->triangles().size()));
m_program->updateUniformMatrix("u_view_projection", core::EngineState::main_camera->getViewProjection());
m_vertex_array->draw(gl::PrimitiveType::ePoints, m_linespace.lines().size());
}
}
}
m_program->updateStorageBuffer("line_buffer", m_linespace.lineBuffer());
m_program->updateUniformUInt("u_mesh", unsigned(m_linespace.m_mesh_id));
m_program->updateUniformUInt("u_triangle_count", unsigned(m_collector.meshCollectors().at(m_linespace.m_mesh_id)->triangles().size()));
m_program->updateUniformMatrix("u_view_projection", core::EngineState::main_camera->getViewProjection());
m_vertex_array->draw(gl::PrimitiveType::ePoints, m_linespace.lines().size());
}
}
}
......@@ -34,7 +34,7 @@ namespace gl
bool isEnabled(EnableParameter parameter)
{
return bool(glIsEnabled(GLenum(parameter)));
return glIsEnabled(GLenum(parameter)) == GL_TRUE;
}
void setEnabled(EnableParameter parameter, bool enabled)
......@@ -97,7 +97,7 @@ namespace gl
bool isNamedString(NamedStringType type, std::string name)
{
return glIsNamedStringARB(GLenum(type), name.c_str());
return glIsNamedStringARB(GLenum(type), name.c_str()) == GL_TRUE;
}
void deleteNamedString(NamedStringType type, std::string name)
......@@ -212,7 +212,7 @@ namespace gl
bool isNamedBufferResident(unsigned buffer)
{
return glIsNamedBufferResidentNV(buffer);
return glIsNamedBufferResidentNV(buffer) == GL_TRUE;
}
void makeNamedBufferResident(unsigned buffer, Access access)
......@@ -277,7 +277,7 @@ namespace gl
bool isTextureHandleResident(uint64_t handle)
{
return glIsTextureHandleResidentARB(handle);
return glIsTextureHandleResidentARB(handle) == GL_TRUE;
}
uint64_t getImageHandle(unsigned texture, int level, bool layered, int layer, ImageUnitFormat format)
......@@ -297,7 +297,7 @@ namespace gl
bool isImageHandleResident(uint64_t handle)
{
return glIsImageHandleResidentARB(handle);
return glIsImageHandleResidentARB(handle) == GL_TRUE;
}
void textureParameter(TextureTarget target, TextureParameter parameter, float value)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment