EBGeometry
Compact, header-only C++ library for fast evaluation of signed distance functions
Loading...
Searching...
No Matches
EBGeometry_Render.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Robert Marskar <robert.marskar@sintef.no>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
20#ifndef EBGEOMETRY_RENDER_HPP
21#define EBGEOMETRY_RENDER_HPP
22
23// Std includes
24#include <atomic>
25#include <cstdint>
26#include <string>
27#include <vector>
28
29// Our includes
30#include "EBGeometry_Array.hpp"
32#include "EBGeometry_Expr.hpp"
33#include "EBGeometry_GPU.hpp"
34#include "EBGeometry_Ray.hpp"
35#include "EBGeometry_Vec.hpp"
36
37namespace EBGeometry {
38
39template <class T>
40class FlatMeshSDF;
41
42template <class T, size_t K>
43class MeshSDF;
44
45template <class T, size_t K, size_t W>
46class TriMeshSDF;
47
48} // namespace EBGeometry
49
50namespace EBGeometry::Render {
51
59template <class S>
60inline constexpr bool primitivesAreFaces = false;
61
66template <class T>
67inline constexpr bool primitivesAreFaces<FlatMeshSDF<T>> = true;
68
74template <class T, size_t K>
75inline constexpr bool primitivesAreFaces<MeshSDF<T, K>> = true;
76
83template <class T, size_t K, size_t W>
84inline constexpr bool primitivesAreFaces<TriMeshSDF<T, K, W>> = true;
85
89enum class ColorBy : uint8_t
90{
91 Uniform,
92 Primitive,
94 Normal
95};
96
101enum class View : uint8_t
102{
103 Front,
104 Back,
105 Right,
106 Left,
107 Top,
108 Bottom,
109 Default
110};
111
120template <class T>
121struct Camera
122{
127
131 T m_yaw = T(35);
132
136 T m_pitch = T(25);
137
141 T m_distance = T(4);
142
146 T m_fieldOfView = T(40);
147
151 Vec3T<T> m_up = Vec3T<T>(T(0), T(1), T(0));
152
160 bool m_orthographic = false;
161
165 T m_nearClip = T(0);
166
175 [[nodiscard]] EBGEOMETRY_HOST
176 static inline Camera
177 fit(const BoundingVolumes::AABBT<T>& a_box, const Vec3T<T>& a_up = Vec3T<T>(T(0), T(1), T(0)));
178
187 [[nodiscard]] EBGEOMETRY_HOST
188 static inline Camera
189 fit(const BoundingVolumes::AABBT<T>& a_box, View a_view, const Vec3T<T>& a_up = Vec3T<T>(T(0), T(1), T(0)));
190
199 [[nodiscard]] EBGEOMETRY_HOST
200 static inline Camera
201 lookAt(const Vec3T<T>& a_eye,
202 const Vec3T<T>& a_target,
203 const Vec3T<T>& a_up = Vec3T<T>(T(0), T(1), T(0)),
204 const T a_fieldOfView = T(40));
205
210 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
211 inline Vec3T<T>
212 eye() const noexcept;
213
221 inline void
222 frame(Vec3T<T>& a_forward, Vec3T<T>& a_right, Vec3T<T>& a_up) const noexcept;
223
231 inline void
232 horizontal(Vec3T<T>& a_first, Vec3T<T>& a_second) const noexcept;
233};
234
239template <class T>
241{
245 uint32_t m_width = 960;
246
250 uint32_t m_height = 960;
251
255 uint32_t m_supersampling = 2;
256
260 uint32_t m_threads = 0;
261
265 bool m_shadows = true;
266
270 bool m_occlusion = true;
271
276 bool m_floor = true;
277
281 bool m_sky = true;
282
286 ColorBy m_colorBy = ColorBy::Normal;
287
291 Vec3T<T> m_color = Vec3T<T>(T(0.80), T(0.42), T(0.18));
292
296 static constexpr uint32_t PrimitiveColors = 16;
297
303 Array<Vec3T<T>, PrimitiveColors> m_primitiveColors = unsetColors();
304
309 bool m_recordPrimitives = false;
310
314 static constexpr uint32_t NoPrimitive = 0xFFFFFFFFU;
315
319 static constexpr uint32_t AllPrimitives = 0xFFFFFFFEU;
320
325 uint32_t m_highlightPrimitive = NoPrimitive;
326
330 Vec3T<T> m_highlightColor = Vec3T<T>(T(1.0), T(0.72), T(0.10));
331
335 Vec3T<T> m_insideColor = Vec3T<T>(T(0.90), T(0.08), T(0.08));
336
341 Vec3T<T> m_cutColor = Vec3T<T>(T(0.95), T(0.86), T(0.50));
342
347 T m_cutOpacity = T(0.6);
348
352 Vec3T<T> m_floorColor = Vec3T<T>(T(0.58), T(0.59), T(0.61));
353
359 bool m_lightFromCamera = true;
360
365 Vec3T<T> m_light = Vec3T<T>(T(-0.45), T(0.75), T(0.55));
366
370 T m_lightIntensity = T(1.05);
371
375 T m_ambient = T(0.35);
376
380 T m_specular = T(0.45);
381
386 T m_shininess = T(32);
387
391 Vec3T<T> m_skyHorizon = Vec3T<T>(T(0.82), T(0.84), T(0.88));
392
396 Vec3T<T> m_skyZenith = Vec3T<T>(T(0.32), T(0.45), T(0.66));
397
401 Vec3T<T> m_background = Vec3T<T>(T(0.16), T(0.17), T(0.19));
402
406 bool m_floorChecker = true;
407
411 T m_floorCheckerSize = T(0);
412
416 bool m_section = false;
417
421 Vec3T<T> m_sectionPoint = Vec3T<T>::zeros();
422
426 Vec3T<T> m_sectionNormal = Vec3T<T>(T(0), T(0), T(1));
427
432 T m_contourWidth = T(2);
433
437 Vec3T<T> m_contourColor = Vec3T<T>(T(0.04), T(0.04), T(0.05));
438
443 T m_isoSpacing = T(0);
444
448 Vec3T<T> m_isoColor = Vec3T<T>(T(0.30), T(0.32), T(0.36));
449
454 T m_sheetOpacity = T(0.35);
455
459 Vec3T<T> m_sheetColor = Vec3T<T>(T(0.95), T(0.96), T(0.97));
460
464 Vec3T<T> m_sheetEdgeColor = Vec3T<T>(T(0.45), T(0.47), T(0.50));
465
471
476 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
477 static inline Array<Vec3T<T>, PrimitiveColors>
478 unsetColors() noexcept;
479};
480
491template <class T>
492[[nodiscard]] EBGEOMETRY_HOST
493inline std::string
494toCode(const Camera<T>& a_camera, const Settings<T>& a_settings);
495
499struct Image
500{
504 uint32_t m_width = 0;
505
509 uint32_t m_height = 0;
510
514 std::vector<uint32_t> m_pixels;
515
521 std::vector<uint32_t> m_primitives;
522
529 [[nodiscard]] inline uint32_t
530 at(const uint32_t a_column, const uint32_t a_row) const noexcept;
531};
532
540[[nodiscard]] inline bool
541writeImage(const Image& a_image, const std::string& a_filename);
542
546struct Stats
547{
551 uint64_t m_rays = 0;
552
556 uint64_t m_hits = 0;
557
561 uint64_t m_insideHits = 0;
562
566 uint64_t m_unresolved = 0;
567
571 bool m_cameraInside = false;
572
576 bool m_complete = true;
577};
578
583{
587 uint32_t m_rgba = 0;
588
592 uint8_t m_hits = 0;
593
597 uint8_t m_insideHits = 0;
598
602 uint8_t m_unresolved = 0;
603
607 uint8_t m_cameraInside = 0;
608
612 uint32_t m_primitive = 0xFFFFFFFFU;
613};
614
615namespace RenderDetail {
616
623{
627 uint32_t m_rgba = 0;
628
632 uint8_t m_hits = 0;
633
637 uint8_t m_insideHits = 0;
638
642 uint8_t m_unresolved = 0;
643
647 uint8_t m_cameraInside = 0;
648
654 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
655 static inline StoredPixel
656 of(const PixelResult& a_result) noexcept
657 {
658 return StoredPixel{
659 a_result.m_rgba, a_result.m_hits, a_result.m_insideHits, a_result.m_unresolved, a_result.m_cameraInside};
660 }
661};
662
671template <class T>
735
736} // namespace RenderDetail
737
747template <class T, class S>
749{
754
759
764
769
777 inline PixelQuery(const S& a_shape, const Camera<T>& a_camera, const Settings<T>& a_settings) noexcept;
778
784 [[nodiscard]] EBGEOMETRY_HOST_DEVICE
785 inline PixelResult
786 operator()(const uint32_t& a_index) const noexcept;
787};
788
795template <class T>
797{
798public:
803 explicit Renderer(const Settings<T>& a_settings = Settings<T>()) noexcept;
804
809 [[nodiscard]] inline Settings<T>&
810 settings() noexcept;
811
816 [[nodiscard]] inline const Settings<T>&
817 settings() const noexcept;
818
827 template <class S>
828 inline Stats
829 render(const S& a_shape, const Camera<T>& a_camera, Image& a_image) const;
830
845 template <class S>
846 inline Stats
847 render(const S& a_shape,
848 const Camera<T>& a_camera,
849 Image& a_image,
850 const std::atomic<bool>& a_cancel,
851 std::atomic<uint32_t>* a_rowsDone = nullptr) const;
852
864 template <class S>
865 inline Stats
866 renderOnDevice(const S& a_deviceShape, const Camera<T>& a_camera, Image& a_image) const;
867
881 template <class S>
882 inline Stats
883 renderOnDevice(const S& a_deviceShape,
884 const Camera<T>& a_camera,
885 Image& a_image,
886 const std::atomic<bool>& a_cancel,
887 std::atomic<uint32_t>* a_rowsDone = nullptr) const;
888
903 template <class S>
904 [[nodiscard]] inline HitT<T>
905 pick(const S& a_shape, const Camera<T>& a_camera, T a_column, T a_row) const;
906
907private:
911 Settings<T> m_settings;
912
917 inline void
918 check(const Camera<T>& a_camera) const;
919
927 inline Stats
928 collect(const std::vector<RenderDetail::StoredPixel>& a_results,
929 std::vector<uint32_t>& a_primitives,
930 Image& a_image) const;
931};
932
933} // namespace EBGeometry::Render
934
935#include "EBGeometry_RenderImplem.hpp"
936
937#endif
A fixed-size array that compiles for both host and device.
Declarations of bounding volume types used in bounding volume hierarchies.
The tape's front end: Expr, a host-side value that describes a composed object, and the free function...
GPU portability layer: host/device decoration macros and backend detection.
#define EBGEOMETRY_HOST_DEVICE
Mark a function as callable from both host and device code (no-op on host compilers).
Definition EBGeometry_GPU.hpp:80
#define EBGEOMETRY_HOST
Mark a function as callable from host code only (no-op on host compilers).
Definition EBGeometry_GPU.hpp:83
Ray queries on any shape: where a ray, or the segment between two points, first crosses its surface (...
bool writeImage(const Image &a_image, const std::string &a_filename)
Write an image to a file, as binary PPM (P6: 8 bits per channel, no alpha), which most image programs...
constexpr bool primitivesAreFaces
Whether a shape's primitives (HitT::m_primitive) are the faces of one object rather than objects: tru...
Definition EBGeometry_Render.hpp:60
View
A direction to look at a box from, for Camera::fit(): along the axes of the plane perpendicular to th...
Definition EBGeometry_Render.hpp:102
@ Back
Yaw 180, pitch 0.
@ Bottom
Pitch -90: straight up the up axis.
@ Front
Yaw 0, pitch 0.
@ Default
The default yaw (35) and pitch (25), from above at an angle.
@ Right
Yaw 90, pitch 0.
@ Left
Yaw -90, pitch 0.
@ Top
Pitch 90: straight down the up axis.
ColorBy
How surfaces are colored.
Definition EBGeometry_Render.hpp:90
@ Normal
The surface normal's direction as a color (each component from -1 to 1 mapped to 0 to 1).
@ Uniform
One color (Settings::m_color) everywhere.
Declaration of 2D and 3D point/vector classes with templated precision, and free functions on them.
Axis-aligned bounding box (AABB) enclosing a set of 3D points.
Definition EBGeometry_BoundingVolumes.hpp:37
Renders shapes into images.
Definition EBGeometry_Render.hpp:797
Renderer(const Settings< T > &a_settings=Settings< T >()) noexcept
Renderer with given settings.
Three-dimensional vector class with arithmetic operators.
Definition EBGeometry_Vec.hpp:258
static constexpr Vec3T< T > zeros() noexcept
Return a vector with x = y = z = 0.
Namespace containing all of EBGeometry's functionality.
Definition EBGeometry_Affine.hpp:26
Fixed-size array with host- and device-callable members.
Definition EBGeometry_Array.hpp:33
Where a ray first crosses a surface.
Definition EBGeometry_Ray.hpp:96
How a query marches, where a shape has no ray form.
Definition EBGeometry_Ray.hpp:155
A camera orbiting a target point.
Definition EBGeometry_Render.hpp:122
T m_fieldOfView
Vertical field of view, in degrees.
Definition EBGeometry_Render.hpp:146
void frame(Vec3T< T > &a_forward, Vec3T< T > &a_right, Vec3T< T > &a_up) const noexcept
The camera's frame: unit vectors forward (towards the target), right and up on the screen.
T m_distance
Distance from the eye to the target.
Definition EBGeometry_Render.hpp:141
bool m_orthographic
Parallel rays instead of rays from the eye: no perspective, so sizes do not shrink with distance.
Definition EBGeometry_Render.hpp:160
Vec3T< T > m_target
The point the camera looks at.
Definition EBGeometry_Render.hpp:126
static Camera fit(const BoundingVolumes::AABBT< T > &a_box, const Vec3T< T > &a_up=Vec3T< T >(T(0), T(1), T(0)))
A camera that sees the whole of a box, from the default direction.
T m_nearClip
How far along each camera ray it starts (0: at the eye): anything nearer is not seen.
Definition EBGeometry_Render.hpp:165
Vec3T< T > m_up
The up axis (need not be of unit length).
Definition EBGeometry_Render.hpp:151
static Camera lookAt(const Vec3T< T > &a_eye, const Vec3T< T > &a_target, const Vec3T< T > &a_up=Vec3T< T >(T(0), T(1), T(0)), const T a_fieldOfView=T(40))
A camera at a given eye, looking at a given point.
Vec3T< T > eye() const noexcept
Where the eye is.
void horizontal(Vec3T< T > &a_first, Vec3T< T > &a_second) const noexcept
Two unit vectors that span the plane perpendicular to the up axis: yaw 90 looks from the first,...
static Camera fit(const BoundingVolumes::AABBT< T > &a_box, View a_view, const Vec3T< T > &a_up=Vec3T< T >(T(0), T(1), T(0)))
A camera that sees the whole of a box, from a given direction.
T m_pitch
Degrees above the plane perpendicular to the up axis, from -90 to 90.
Definition EBGeometry_Render.hpp:136
T m_yaw
Degrees about the up axis.
Definition EBGeometry_Render.hpp:131
An image: width x height pixels, row by row from the top, each 0xRRGGBBAA.
Definition EBGeometry_Render.hpp:500
std::vector< uint32_t > m_primitives
With Settings::m_recordPrimitives, for each pixel the primitive its first ray hit (HitT::m_primitive)...
Definition EBGeometry_Render.hpp:521
std::vector< uint32_t > m_pixels
The pixels, row by row from the top.
Definition EBGeometry_Render.hpp:514
uint32_t at(const uint32_t a_column, const uint32_t a_row) const noexcept
One pixel.
One pixel of a rendered image: the functor that Renderer runs once per pixel index,...
Definition EBGeometry_Render.hpp:749
RenderDetail::CameraView< T > m_view
The camera's eye and axes, worked out once rather than per pixel.
Definition EBGeometry_Render.hpp:768
PixelQuery(const S &a_shape, const Camera< T > &a_camera, const Settings< T > &a_settings) noexcept
The pixel functor for a shape, a camera and settings.
Settings< T > m_settings
The settings.
Definition EBGeometry_Render.hpp:763
S m_shape
The shape.
Definition EBGeometry_Render.hpp:753
PixelResult operator()(const uint32_t &a_index) const noexcept
Shade pixel a_index (row a_index / width, column a_index % width).
Camera< T > m_camera
The camera.
Definition EBGeometry_Render.hpp:758
What PixelQuery computes for one pixel.
Definition EBGeometry_Render.hpp:583
What every pixel needs from the camera, worked out once per frame: the eye, the view's axes and the f...
Definition EBGeometry_Render.hpp:673
Vec3T< T > m_up
Unit up of the image.
Definition EBGeometry_Render.hpp:692
T m_distance
Distance from the eye to the target.
Definition EBGeometry_Render.hpp:717
Vec3T< T > m_second
Horizontal unit vectors (see Camera::horizontal()).
Definition EBGeometry_Render.hpp:707
Vec3T< T > m_right
Unit right of the image.
Definition EBGeometry_Render.hpp:687
Vec3T< T > m_eye
The eye.
Definition EBGeometry_Render.hpp:677
bool m_orthographic
Whether the camera is orthographic.
Definition EBGeometry_Render.hpp:733
Vec3T< T > m_forward
Unit direction the camera looks in.
Definition EBGeometry_Render.hpp:682
T m_footprint
How wide a pixel is at distance t along a camera ray: m_footprint + m_footprintPerLength t (the first...
Definition EBGeometry_Render.hpp:723
Vec3T< T > m_axis
Unit up axis of the scene.
Definition EBGeometry_Render.hpp:697
T m_tanHalf
Tangent of half the vertical field of view.
Definition EBGeometry_Render.hpp:712
Vec3T< T > m_first
Horizontal unit vectors (see Camera::horizontal()).
Definition EBGeometry_Render.hpp:702
T m_footprintPerLength
See m_footprint.
Definition EBGeometry_Render.hpp:728
A pixel as a render stores it: PixelResult without the object, which is stored apart and only when as...
Definition EBGeometry_Render.hpp:623
static StoredPixel of(const PixelResult &a_result) noexcept
The stored part of a pixel's result.
Definition EBGeometry_Render.hpp:656
uint32_t m_rgba
The pixel, 0xRRGGBBAA.
Definition EBGeometry_Render.hpp:627
What to render and how. A plain value; every field has a default.
Definition EBGeometry_Render.hpp:241
RayOptions< T > m_rays
How rays march (see firstHit()). A scale of 0 takes the shape's box diagonal, or the camera distance ...
Definition EBGeometry_Render.hpp:470
static Array< Vec3T< T >, PrimitiveColors > unsetColors() noexcept
Every entry of m_primitiveColors unset.
What a render saw.
Definition EBGeometry_Render.hpp:547