medfall

A super great game engine
Log | Files | Refs

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 }