|
|
@ -11,107 +11,114 @@ |
|
|
|
|
|
|
|
// TODO: Namespace this correctly
|
|
|
|
|
|
|
|
using vec2 = gp::math::vec2_g<>; |
|
|
|
using vec3 = gp::math::vec3_g<>; |
|
|
|
using vec4 = gp::math::vec4_g<>; |
|
|
|
|
|
|
|
struct camera{ |
|
|
|
vec3 position; |
|
|
|
vec3 normal; |
|
|
|
}; |
|
|
|
|
|
|
|
using index_t = size_t; |
|
|
|
using distance_t = gp_config::rendering::default_type; |
|
|
|
using color_t = GP_CONFIG__RENDERING__COLOR_T; |
|
|
|
|
|
|
|
struct render_point{ |
|
|
|
distance_t distance; |
|
|
|
index_t material; |
|
|
|
|
|
|
|
bool operator<(const render_point& rhs) { |
|
|
|
return distance < rhs.distance; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
using sdf_t = gp::function<render_point(vec3&)>; |
|
|
|
using material_t = gp::function<color_t(vec3&)>; |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A pure ray-marching renderer. Prints pixels on order. |
|
|
|
*/ |
|
|
|
class renderer { |
|
|
|
using g_t = gp_config::rendering::default_type; |
|
|
|
constexpr static auto epsilon = gp_config::rendering::epsilon; |
|
|
|
public: |
|
|
|
gp::indexed_array<sdf_t, 4096> scene_elements; |
|
|
|
gp::indexed_array<material_t, 4096> materials; |
|
|
|
gp::buddy<> allocator; |
|
|
|
material_t sky_box; |
|
|
|
vec2 _resolution{128,64}; |
|
|
|
camera _camera{{0, 0, -1}, {0, 0, 0}}; |
|
|
|
vec2 _fov{90, 45}; |
|
|
|
distance_t projection_start = 1; |
|
|
|
distance_t projection_end = 50; |
|
|
|
size_t passes = 12; |
|
|
|
|
|
|
|
renderer(gp::buffer<char> allocation_buffer) |
|
|
|
: allocator(allocation_buffer.begin().data, allocation_buffer.size()) |
|
|
|
, sky_box{gp::reference_wrapper<gp::buddy<>>{allocator}} |
|
|
|
{} |
|
|
|
|
|
|
|
render_point sdf(vec3& render_target) { |
|
|
|
return gp::min_of( |
|
|
|
scene_elements.begin(), |
|
|
|
scene_elements.end(), |
|
|
|
[&](auto& p){ |
|
|
|
return p(render_target); |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
auto& get_allocator() { |
|
|
|
return allocator; |
|
|
|
} |
|
|
|
|
|
|
|
color_t render(vec2 pixel) { |
|
|
|
g_t depth = projection_start; |
|
|
|
vec3 target = _camera.normal; |
|
|
|
auto half_res = _resolution/vec2{2.0, 2.0}; |
|
|
|
pixel = pixel - half_res; |
|
|
|
pixel = pixel / half_res; |
|
|
|
pixel = pixel * _fov; |
|
|
|
pixel = pixel / vec2{180, 180} * vec2{gp::math::pi<g_t>,gp::math::pi<g_t>}; |
|
|
|
|
|
|
|
// Y-rot (adjusts x)
|
|
|
|
target = vec3{ |
|
|
|
target.x*gp::math::cos(pixel.x) + target.z*gp::math::sin(pixel.x), |
|
|
|
target.y, |
|
|
|
-target.x*gp::math::sin(pixel.x)+target.z*gp::math::cos(pixel.x) |
|
|
|
}; |
|
|
|
// X-rot (adjusts y)
|
|
|
|
target = vec3{ |
|
|
|
target.x, |
|
|
|
target.y*gp::math::cos(pixel.y) - target.z*gp::math::sin(pixel.y), |
|
|
|
target.y*gp::math::sin(pixel.y) + target.z*gp::math::cos(pixel.y) |
|
|
|
}; |
|
|
|
|
|
|
|
vec3 render_target{_camera.position}; |
|
|
|
for(int i = 1; i < passes; ++i) { |
|
|
|
render_point distance = sdf(render_target); |
|
|
|
|
|
|
|
if(distance.distance < epsilon) { |
|
|
|
return materials[distance.material](render_target); |
|
|
|
} |
|
|
|
|
|
|
|
depth += distance.distance; |
|
|
|
|
|
|
|
if(depth >= projection_end) { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
render_target = _camera.position+depth*target; |
|
|
|
namespace gp { |
|
|
|
namespace math { |
|
|
|
namespace rendering { |
|
|
|
|
|
|
|
using vec2 = gp::math::vec2_g<>; |
|
|
|
using vec3 = gp::math::vec3_g<>; |
|
|
|
using vec4 = gp::math::vec4_g<>; |
|
|
|
|
|
|
|
struct camera{ |
|
|
|
vec3 position; |
|
|
|
vec3 normal; |
|
|
|
}; |
|
|
|
|
|
|
|
using index_t = size_t; |
|
|
|
using distance_t = gp_config::rendering::default_type; |
|
|
|
using color_t = GP_CONFIG__RENDERING__COLOR_T; |
|
|
|
|
|
|
|
struct render_point{ |
|
|
|
distance_t distance; |
|
|
|
index_t material; |
|
|
|
|
|
|
|
bool operator<(const render_point& rhs) { |
|
|
|
return distance < rhs.distance; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
using sdf_t = gp::function<render_point(vec3&)>; |
|
|
|
using material_t = gp::function<color_t(vec3&)>; |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief A pure ray-marching renderer. Prints pixels on order. |
|
|
|
*/ |
|
|
|
class renderer { |
|
|
|
using g_t = gp_config::rendering::default_type; |
|
|
|
constexpr static auto epsilon = gp_config::rendering::epsilon; |
|
|
|
public: |
|
|
|
gp::indexed_array<sdf_t, 4096> scene_elements; |
|
|
|
gp::indexed_array<material_t, 4096> materials; |
|
|
|
gp::buddy<> allocator; |
|
|
|
material_t sky_box; |
|
|
|
vec2 _resolution{128,64}; |
|
|
|
camera _camera{{0, 0, -5}, {0, 0, 0}}; |
|
|
|
vec2 _fov{90, 45}; |
|
|
|
distance_t projection_start = 1; |
|
|
|
distance_t projection_end = 50; |
|
|
|
size_t passes = 12; |
|
|
|
|
|
|
|
renderer(gp::buffer<char> allocation_buffer) |
|
|
|
: allocator(allocation_buffer.begin().data, allocation_buffer.size()) |
|
|
|
, sky_box{gp::reference_wrapper<gp::buddy<>>{allocator}} |
|
|
|
{} |
|
|
|
|
|
|
|
render_point sdf(vec3& render_target) { |
|
|
|
return gp::min_of( |
|
|
|
scene_elements.begin(), |
|
|
|
scene_elements.end(), |
|
|
|
[&](auto& p){ |
|
|
|
return p(render_target); |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
auto& get_allocator() { |
|
|
|
return allocator; |
|
|
|
} |
|
|
|
|
|
|
|
color_t render(vec2 pixel) { |
|
|
|
g_t depth = projection_start; |
|
|
|
vec3 target = _camera.normal; |
|
|
|
auto half_res = _resolution/vec2{2.0, 2.0}; |
|
|
|
pixel = pixel - half_res; |
|
|
|
pixel = pixel / half_res; |
|
|
|
pixel = pixel * _fov; |
|
|
|
pixel = pixel / vec2{180, 180} * vec2{gp::math::pi<g_t>,gp::math::pi<g_t>}; |
|
|
|
|
|
|
|
// Y-rot (adjusts x)
|
|
|
|
target = vec3{ |
|
|
|
target.x*gp::math::cos(pixel.x) + target.z*gp::math::sin(pixel.x), |
|
|
|
target.y, |
|
|
|
-target.x*gp::math::sin(pixel.x)+target.z*gp::math::cos(pixel.x) |
|
|
|
}; |
|
|
|
// X-rot (adjusts y)
|
|
|
|
target = vec3{ |
|
|
|
target.x, |
|
|
|
target.y*gp::math::cos(pixel.y) - target.z*gp::math::sin(pixel.y), |
|
|
|
target.y*gp::math::sin(pixel.y) + target.z*gp::math::cos(pixel.y) |
|
|
|
}; |
|
|
|
|
|
|
|
vec3 render_target{_camera.position}; |
|
|
|
for(int i = 0; i < passes; ++i) { |
|
|
|
render_point distance = sdf(render_target); |
|
|
|
|
|
|
|
if(distance.distance < epsilon) { |
|
|
|
return materials[distance.material](render_target); |
|
|
|
} |
|
|
|
|
|
|
|
depth += distance.distance; |
|
|
|
|
|
|
|
if(depth >= projection_end) { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
render_target = _camera.position+depth*target; |
|
|
|
} |
|
|
|
return sky_box(render_target); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
return sky_box(render_target); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |