medfall

A super great game engine
Log | Files | Refs

renderer.h (8161B)


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