renderer.h (8837B)
1 #pragma once 2 3 #include "intrinsics.h" 4 #include "array.h" 5 #include "linear_algebra.h" 6 #include "stringhash.h" 7 8 /* 9 * forward declare things so only the implementation includes the full GL headers 10 */ 11 12 typedef u32 VB; 13 typedef u32 IB; 14 typedef u32 Texture; 15 typedef u32 FramebufferObject; 16 17 enum OutputSlots { 18 OUTPUT_ALBEDO, 19 OUTPUT_NORMAL, 20 21 OUTPUT_DEPTH, 22 23 OUTPUTS_COUNT, 24 }; 25 26 #define RENDERER_MAX_TEXTURES 4 27 #define RENDERER_MAX_TEXTURE_BUFFERS 4 28 29 enum CullFace { 30 CULLFACE_BACK, 31 CULLFACE_FRONT, 32 CULLFACE_DISABLED, 33 }; 34 35 enum DepthFunc { 36 DEPTHFUNC_LESS, 37 DEPTHFUNC_EQUAL, 38 DEPTHFUNC_ALWAYS, 39 DEPTHFUNC_DISABLED, // also disables writing 40 }; 41 42 enum BufferUsage { 43 BUFFERUSAGE_STATIC, 44 BUFFERUSAGE_DYNAMIC, // TODO: remove dynamic? 45 BUFFERUSAGE_STREAM, 46 }; 47 48 enum PrimitiveType { 49 PRIMITIVETYPE_TRIANGLES, 50 PRIMITIVETYPE_TRIANGLE_STRIP, 51 PRIMITIVETYPE_POINTS, 52 PRIMITIVETYPE_LINES, 53 }; 54 55 enum TextureFormat { 56 TEXFMT_INVALID, 57 58 TEXFMT_R_U8, 59 TEXFMT_R_U8NORM, 60 TEXFMT_R_U16, 61 TEXFMT_R_FLOAT, 62 63 TEXFMT_RGB_U8, 64 TEXFMT_RGB_U8_SRGB, 65 TEXFMT_RGB_HALF, 66 TEXFMT_RGB_FLOAT, 67 68 TEXFMT_RGBA_U8, 69 TEXFMT_RGBA_U8_SRGB, 70 TEXFMT_RGBA_FLOAT, 71 72 TEXFMT_DEPTH, 73 74 TEXFMT_BC1, 75 TEXFMT_BC1_SRGB, 76 TEXFMT_BC4, 77 TEXFMT_BC5, 78 }; 79 80 enum TextureWrapMode { 81 TEXWRAP_REPEAT, 82 TEXWRAP_CLAMP, 83 TEXWRAP_MIRROR, 84 TEXWRAP_BORDER, 85 }; 86 87 enum TextureFilterMode { 88 TEXFILTER_LINEAR, 89 TEXFILTER_POINT, 90 }; 91 92 enum FramebufferAttachment { 93 FB_COLOUR, 94 FB_DEPTH, 95 FB_NORMAL, 96 }; 97 98 struct Shader { 99 u32 program; 100 u32 uniforms[ 16 ]; 101 u32 textures[ RENDERER_MAX_TEXTURES ]; 102 }; 103 104 struct FB { 105 FramebufferObject fbo; 106 StaticArray< Texture, OUTPUTS_COUNT > textures = { }; 107 u32 width, height; 108 }; 109 110 struct UniformBinding { 111 u32 ubo; 112 u32 offset; 113 u32 size; 114 }; 115 116 struct RenderState { 117 struct Uniform { 118 u32 name_hash; 119 UniformBinding binding; 120 }; 121 122 struct T { 123 u32 name_hash; 124 Texture texture; 125 }; 126 127 Uniform uniforms[ 16 ]; 128 T textures[ RENDERER_MAX_TEXTURES ]; 129 size_t num_uniforms = 0; 130 size_t num_textures = 0; 131 132 u8 pass = U8_MAX; 133 const Shader * shader = NULL; 134 DepthFunc depth_func = DEPTHFUNC_LESS; 135 CullFace cull_face = CULLFACE_BACK; 136 bool disable_depth_writes = false; 137 bool disable_colour_writes = false; 138 bool enable_alpha_blending = false; 139 bool wireframe = false; 140 141 void set_uniform( StringHash name, UniformBinding binding ) { 142 for( size_t i = 0; i < num_uniforms; i++ ) { 143 if( uniforms[ i ].name_hash == name.hash ) { 144 uniforms[ i ].binding = binding; 145 return; 146 } 147 } 148 149 uniforms[ num_uniforms ].name_hash = name.hash; 150 uniforms[ num_uniforms ].binding = binding; 151 num_uniforms++; 152 } 153 154 void set_texture( StringHash name, Texture texture ) { 155 for( size_t i = 0; i < num_textures; i++ ) { 156 if( textures[ i ].name_hash == name.hash ) { 157 textures[ i ].texture = texture; 158 return; 159 } 160 } 161 162 textures[ num_textures ].name_hash = name.hash; 163 textures[ num_textures ].texture = texture; 164 num_textures++; 165 } 166 }; 167 168 enum VertexFormat { 169 VERTEXFMT_U8x3, 170 VERTEXFMT_U8x4, 171 172 VERTEXFMT_U16x4, 173 174 VERTEXFMT_HALFx2, 175 VERTEXFMT_HALFx3, 176 VERTEXFMT_HALFx4, 177 178 VERTEXFMT_FLOATx2, 179 VERTEXFMT_FLOATx3, 180 VERTEXFMT_FLOATx4, 181 }; 182 183 enum IndexFormat { 184 INDEXFMT_U16, 185 INDEXFMT_U32, 186 }; 187 188 struct Mesh { 189 u32 num_vertices; 190 PrimitiveType primitive_type; 191 u32 vao; 192 VB positions; 193 VB normals; 194 VB tex_coords0; 195 VB tex_coords1; 196 VB colours; 197 VB joints; 198 VB weights; 199 IB indices; 200 IndexFormat indices_format; 201 }; 202 203 struct MeshConfig { 204 MeshConfig() { 205 positions = 0; 206 normals = 0; 207 tex_coords0 = 0; 208 tex_coords1 = 0; 209 colours = 0; 210 joints = 0; 211 weights = 0; 212 } 213 214 VB unified_buffer = 0; 215 u32 stride = 0; 216 217 union { 218 struct { 219 VB positions; 220 VB normals; 221 VB tex_coords0; 222 VB tex_coords1; 223 VB colours; 224 VB joints; 225 VB weights; 226 }; 227 struct { 228 u32 positions_offset; 229 u32 normals_offset; 230 u32 tex_coords0_offset; 231 u32 tex_coords1_offset; 232 u32 colours_offset; 233 u32 joints_offset; 234 u32 weights_offset; 235 }; 236 }; 237 238 VertexFormat positions_format = VERTEXFMT_FLOATx3; 239 VertexFormat normals_format = VERTEXFMT_FLOATx3; 240 VertexFormat tex_coords0_format = VERTEXFMT_FLOATx2; 241 VertexFormat tex_coords1_format = VERTEXFMT_FLOATx2; 242 VertexFormat colours_format = VERTEXFMT_FLOATx3; 243 VertexFormat joints_format = VERTEXFMT_U16x4; 244 VertexFormat weights_format = VERTEXFMT_FLOATx4; 245 IndexFormat indices_format = INDEXFMT_U32; 246 247 IB indices = 0; 248 u32 num_vertices = 0; 249 250 PrimitiveType primitive_type = PRIMITIVETYPE_TRIANGLES; 251 }; 252 253 struct TextureConfig { 254 u32 width = 0; 255 u32 height = 0; 256 257 const void * data = NULL; 258 u32 data_size; 259 260 TextureFormat format = TEXFMT_INVALID; 261 TextureWrapMode wrap = TEXWRAP_REPEAT; 262 TextureFilterMode filter = TEXFILTER_LINEAR; 263 bool has_mipmaps = false; 264 265 v4 border_colour; 266 }; 267 268 struct RenderPass { 269 const char * name = NULL; 270 271 FB target = { }; 272 273 bool clear_colour = false; 274 v4 colour = v4( 0 ); 275 276 bool clear_depth = false; 277 float depth = 1.0f; 278 279 FB msaa_source = { }; 280 }; 281 282 struct FramebufferConfig { 283 struct FramebufferTexture { 284 TextureConfig config; 285 FramebufferAttachment attachment; 286 }; 287 288 StaticArray< FramebufferTexture, OUTPUTS_COUNT > textures = { }; 289 int msaa_samples = 0; 290 }; 291 292 enum ClearColourBool { RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_COLOUR_DO }; 293 enum ClearDepthBool { RENDERER_CLEAR_DEPTH_DONT, RENDERER_CLEAR_DEPTH_DO }; 294 295 void renderer_init(); 296 void renderer_term(); 297 298 void renderer_begin_frame(); 299 void renderer_end_frame(); 300 301 u8 renderer_add_pass( const RenderPass & config ); 302 u8 renderer_add_pass( const char * name, ClearColourBool clear_colour = RENDERER_CLEAR_COLOUR_DONT, ClearDepthBool clear_depth = RENDERER_CLEAR_DEPTH_DONT ); 303 u8 renderer_add_pass( const char * name, FB target, ClearColourBool clear_colour = RENDERER_CLEAR_COLOUR_DONT, ClearDepthBool clear_depth = RENDERER_CLEAR_DEPTH_DONT ); 304 void renderer_resolve_msaa( FB fb ); 305 306 u32 renderer_num_draw_calls(); 307 u32 renderer_num_vertices(); 308 309 Texture renderer_blue_noise(); 310 311 UniformBinding renderer_upload_uniforms( const void * data, size_t size ); 312 313 VB renderer_new_vb( const void * data = NULL, u32 len = 0, BufferUsage usage = BUFFERUSAGE_STATIC ); 314 void renderer_delete_vb( VB vb ); 315 316 IB renderer_new_ib( const void * data = NULL, u32 len = 0, BufferUsage usage = BUFFERUSAGE_STATIC ); 317 void renderer_delete_ib( IB ib ); 318 319 Texture renderer_new_texture( const TextureConfig & config ); 320 void renderer_delete_texture( Texture texture ); 321 322 FB renderer_new_fb( TextureConfig texture_format, FramebufferAttachment attachment ); 323 FB renderer_new_fb( const FramebufferConfig & config ); 324 void renderer_delete_fb( FB fb ); 325 326 Shader renderer_new_shader( array< const char * > srcs ); 327 void renderer_delete_shader( Shader shader ); 328 329 Mesh renderer_new_mesh( MeshConfig config ); 330 void renderer_draw_mesh( const Mesh & mesh, const RenderState & state ); 331 void renderer_draw_instances( const Mesh & mesh, const RenderState & state, u32 num_instances, VB instace_data ); 332 void renderer_delete_mesh( const Mesh & mesh ); 333 334 void renderer_draw_fullscreen_triangle( const RenderState & state ); 335 336 /* 337 * renderer_new_*( array ) helpers 338 */ 339 340 template< typename T > 341 VB renderer_new_vb( const array< T > data, BufferUsage usage = BUFFERUSAGE_STATIC ) { 342 return renderer_new_vb( data.ptr(), checked_cast< u32 >( data.num_bytes() ), usage ); 343 } 344 345 template< typename T > 346 IB renderer_new_ib( const array< T > data, BufferUsage usage = BUFFERUSAGE_STATIC ) { 347 return renderer_new_ib( data.ptr(), checked_cast< u32 >( data.num_bytes() ), usage ); 348 } 349 350 /* 351 * renderer_uniform helper 352 */ 353 354 template< typename T > 355 constexpr size_t renderer_ubo_alignment() { 356 return min( align4( sizeof( T ) ), 4 * sizeof( float ) ); 357 } 358 359 template<> 360 constexpr size_t renderer_ubo_alignment< v3 >() { 361 return 4 * sizeof( float ); 362 } 363 364 template< typename T > 365 constexpr size_t renderer_ub_alignment() { 366 return renderer_ubo_alignment< T >(); 367 } 368 369 template< typename T > 370 constexpr size_t renderer_uniforms_size( size_t size ) { 371 return sizeof( T ) + align_power_of_2( size, renderer_ubo_alignment< T >() ); 372 } 373 374 template< typename S, typename T, typename... Rest > 375 constexpr size_t renderer_uniforms_size( size_t size ) { 376 return renderer_uniforms_size< T, Rest... >( sizeof( S ) + align_power_of_2( size, renderer_ubo_alignment< S >() ) ); 377 } 378 379 inline void renderer_serialise_uniforms( char * buf, size_t len ) { } 380 381 template< typename T, typename... Rest > 382 inline void renderer_serialise_uniforms( char * buf, size_t len, const T & first, Rest... rest ) { 383 len = align_power_of_2( len, renderer_ubo_alignment< T >() ); 384 memcpy( buf + len, &first, sizeof( first ) ); 385 renderer_serialise_uniforms( buf, len + sizeof( first ), rest... ); 386 } 387 388 template< typename... Rest > 389 inline UniformBinding renderer_uniforms( Rest... rest ) { 390 constexpr size_t buf_size = renderer_uniforms_size< Rest... >( 0 ); 391 char buf[ buf_size ]; 392 memset( buf, 0, sizeof( buf ) ); 393 renderer_serialise_uniforms( buf, 0, rest... ); 394 return renderer_upload_uniforms( buf, sizeof( buf ) ); 395 }