|  |  | @ -24,9 +24,6 @@ typedef void (*rk_MultiDrawElementsIndirectFunc)(rk_uint, rk_uint, const void *, | 
			
		
	
		
		
			
				
					
					|  |  |  | static rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr; |  |  |  | static rk_DrawElementsInstancedBaseInstanceFunc rk_DrawElementsInstancedBaseInstance = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  | static rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr; |  |  |  | static rk_MultiDrawElementsIndirectFunc rk_MultiDrawElementsIndirect = nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static rk_shader const * rk_current_shader = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static rk_vertices const * rk_current_vertices = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static void rk_gl_printf(char const * message) { |  |  |  | static void rk_gl_printf(char const * message) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     printf("[GL] %s\n", message); |  |  |  |     printf("[GL] %s\n", message); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -143,7 +140,7 @@ rk_shader_t rk_load_shader( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_print_program_infolog(shader->program); |  |  |  |     rk_print_program_infolog(shader->program); | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_printf("Done."); |  |  |  |     rk_printf("Done."); | 
			
		
	
		
		
			
				
					
					|  |  |  |     glReleaseShaderCompiler(); |  |  |  |     glReleaseShaderCompiler(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     return shader; |  |  |  |     return reinterpret_cast<rk_shader_t>(shader); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | rk_input_t rk_resolve_input( |  |  |  | rk_input_t rk_resolve_input( | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -174,7 +171,7 @@ rk_texture_t rk_create_texture( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_uint height, |  |  |  |     rk_uint height, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_uint nlevels, |  |  |  |     rk_uint nlevels, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_texture_flags flags, |  |  |  |     rk_texture_flags flags, | 
			
		
	
		
		
			
				
					
					|  |  |  |     void const * pixels) { |  |  |  |     rk_ubyte const * pixels) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if (!width || !height || !pixels) { |  |  |  |     if (!width || !height || !pixels) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return nullptr; |  |  |  |         return nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -250,7 +247,7 @@ rk_texture_t rk_create_texture( | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     texture->nlevels = nlevels; |  |  |  |     texture->nlevels = nlevels; | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindTexture(target, 0); |  |  |  |     glBindTexture(target, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     return texture; |  |  |  |     return reinterpret_cast<rk_texture_t>(texture); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | rk_triangles_t rk_create_triangles( |  |  |  | rk_triangles_t rk_create_triangles( | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -270,33 +267,30 @@ rk_triangles_t rk_create_triangles( | 
			
		
	
		
		
			
				
					
					|  |  |  |     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); |  |  |  |     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, 0); |  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindVertexArray(0); |  |  |  |     glBindVertexArray(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     return triangles; |  |  |  |     return reinterpret_cast<rk_triangles_t>(triangles); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | rk_vertices_t rk_create_vertices( |  |  |  | rk_vertices_t rk_create_vertices( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertex_format const * format, |  |  |  |     rk_vertex_format const * format, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_uint nvertices, |  |  |  |     rk_uint nvertices, | 
			
		
	
		
		
			
				
					
					|  |  |  |     void const * _vertices, |  |  |  |     rk_ubyte const * _vertices, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     rk_uint nindices, |  |  |  |     rk_uint nindices, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_ushort const * indices) { |  |  |  |     rk_ushort const * indices) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!format || !nvertices || !_vertices || !nindices || !indices) { |  |  |  |     if (!format || !nvertices || !_vertices || !nindices || !indices) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return nullptr; |  |  |  |         return nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     unsigned format_size = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned vertex_size = 0; |  |  |  |     unsigned vertex_size = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned nattribs = 0; |  |  |  |     for (rk_vertex_format const * f = format; *f; ++f, ++format_size) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (rk_vertex_format const * f = format; *f; ++f) { |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         switch (*f & RK_VERTEX_FORMAT_MASK) { |  |  |  |         switch (*f & RK_VERTEX_FORMAT_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_FLOAT: |  |  |  |             case RK_VERTEX_FORMAT_VEC3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 vertex_size += sizeof(rk_vec3_float); |  |  |  |                 vertex_size += sizeof(rk_vec3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |                 nattribs += 1; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_INT10: |  |  |  |             case RK_VERTEX_FORMAT_VEC3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 vertex_size += sizeof(rk_vec3_int10); |  |  |  |                 vertex_size += sizeof(rk_vec3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |                 nattribs += 1; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_UINT10: |  |  |  |             case RK_VERTEX_FORMAT_VEC3_UINT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 vertex_size += sizeof(rk_vec3_uint10); |  |  |  |                 vertex_size += sizeof(rk_vec3_uint10); | 
			
		
	
		
		
			
				
					
					|  |  |  |                 nattribs += 1; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             default: |  |  |  |             default: | 
			
		
	
		
		
			
				
					
					|  |  |  |                 rk_printf("rk_create_vertices(): invalid format."); |  |  |  |                 rk_printf("rk_create_vertices(): invalid format."); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -304,49 +298,20 @@ rk_vertices_t rk_create_vertices( | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!vertex_size) { |  |  |  |     if (!format_size) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         rk_printf("rk_create_vertices(): empty format."); |  |  |  |         rk_printf("rk_create_vertices(): empty format."); | 
			
		
	
		
		
			
				
					
					|  |  |  |         return nullptr; |  |  |  |         return nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices * const vertices = new rk_vertices; |  |  |  |     rk_vertices * const vertices = new rk_vertices; | 
			
		
	
		
		
			
				
					
					|  |  |  |     vertices->vertex_size = vertex_size; |  |  |  |     vertices->nvertices = nvertices; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glGenVertexArrays(1, &vertices->array); |  |  |  |     vertices->nindices = nindices; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glBindVertexArray(vertices->array); |  |  |  |     vertices->format = new rk_vertex_format[format_size + 1]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glGenBuffers(1, &vertices->vertices); |  |  |  |     memcpy(vertices->format, format, (format_size + 1) * sizeof(rk_vertex_format)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, vertices->vertices); |  |  |  |     vertices->vertices = new rk_ubyte[nvertices * vertex_size]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glBufferData(GL_ARRAY_BUFFER, nvertices * vertex_size, _vertices, GL_STATIC_DRAW); |  |  |  |     memcpy(vertices->vertices, _vertices, nvertices * vertex_size); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, 0); |  |  |  |     vertices->indices = new rk_ushort[nindices]; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     glBindVertexBuffer(RK_VERTICES_BINDING, vertices->vertices, 0, vertices->vertex_size); |  |  |  |     memcpy(vertices->indices, indices, nindices * sizeof(rk_ushort)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     for (unsigned attrib = 0; attrib < nattribs; ++attrib) { |  |  |  |     return reinterpret_cast<rk_vertices_t>(vertices); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glEnableVertexAttribArray(attrib); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     vertices->layout = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned offset = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (rk_vertex_format const * f = format; *f; ++f) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         GLboolean const norm = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         switch (*f & RK_VERTEX_FORMAT_MASK) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_FLOAT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 glVertexAttribFormat(vertices->layout++, 3, GL_FLOAT, GL_FALSE, offset); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 offset += sizeof(rk_vec3_float); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_INT10: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 glVertexAttribFormat(vertices->layout++, 4, GL_INT_2_10_10_10_REV, norm, offset); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 offset += sizeof(rk_vec3_int10); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             case RK_VERTEX_FORMAT_VEC3_UINT10: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 glVertexAttribFormat(vertices->layout++, 4, GL_UNSIGNED_INT_2_10_10_10_REV, norm, offset); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 offset += sizeof(rk_vec3_uint10); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (unsigned attrib = 0; attrib < nattribs; ++attrib) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         glVertexAttribBinding(attrib, RK_VERTICES_BINDING); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glGenBuffers(1, &vertices->indices); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertices->indices); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBufferData(GL_ELEMENT_ARRAY_BUFFER, nindices * sizeof(rk_ushort), indices, GL_STATIC_DRAW); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindVertexArray(0); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return vertices; |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static void rk_pack_vec3_float( |  |  |  | static void rk_pack_vec3_float( | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -480,7 +445,6 @@ static void rk_pack_mat3_int10_norm( | 
			
		
	
		
		
			
				
					
					|  |  |  |     #undef _convert |  |  |  |     #undef _convert | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | //TODO: multiple batches per vertices with their own buffers |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | rk_batch_t rk_create_batch( |  |  |  | rk_batch_t rk_create_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices_t _vertices, |  |  |  |     rk_vertices_t _vertices, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_uint max_size, |  |  |  |     rk_uint max_size, | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -491,98 +455,151 @@ rk_batch_t rk_create_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_printf("rk_create_batch(): invalid parameters."); |  |  |  |         rk_printf("rk_create_batch(): invalid parameters."); | 
			
		
	
		
		
			
				
					
					|  |  |  |         return nullptr; |  |  |  |         return nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     unsigned vertex_size = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for (rk_vertex_format const * f = vertices->format; *f; ++f) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         switch (*f & RK_VERTEX_FORMAT_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 vertex_size += sizeof(rk_vec3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 vertex_size += sizeof(rk_vec3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_UINT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 vertex_size += sizeof(rk_vec3_uint10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned nparams = 0; |  |  |  |     unsigned nparams = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     unsigned params_size = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (params_format) { |  |  |  |     if (params_format) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         for ( ; params_format[nparams]; ++nparams); |  |  |  |         for (rk_param_format const * f = params_format; *f; ++f, ++nparams) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             switch (*f & RK_PARAM_FORMAT_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 case RK_PARAM_FORMAT_VEC3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     params_size += sizeof(rk_vec3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 case RK_PARAM_FORMAT_VEC3_SHORT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     params_size += sizeof(rk_vec3_short); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 case RK_PARAM_FORMAT_VEC3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     params_size += sizeof(rk_vec3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 case RK_PARAM_FORMAT_MAT3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     params_size += sizeof(rk_mat3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 case RK_PARAM_FORMAT_MAT3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     params_size += sizeof(rk_mat3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 default: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     rk_printf("rk_create_batch(): invalid param format."); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     return nullptr; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_batch * batch = new rk_batch; |  |  |  |     rk_batch * batch = new rk_batch; | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->max_size = max_size; |  |  |  |     batch->max_size = max_size; | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->max_meshes = max_meshes; |  |  |  |     batch->max_meshes = max_meshes; | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->nparams = nparams; |  |  |  |     batch->nparams = nparams; | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->commands_size = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->packed_size = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->indices = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->commands = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->params = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->commands_buffer = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->params_array = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned packed_size = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (nparams) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         batch->params = new rk_parameter[nparams]; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_parameter * param = batch->params; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         for (rk_param_format const * f = params_format; *f; ++f, ++param) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             param->offset = packed_size; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             bool const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             switch (*f & RK_PARAM_FORMAT_MASK) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_FLOAT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->size = sizeof(rk_vec3_float); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->packer = rk_pack_vec3_float; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_SHORT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->size = sizeof(rk_vec3_short); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->packer = norm ? rk_pack_vec3_short_norm : rk_pack_vec3_short; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_INT10: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->size = sizeof(rk_vec3_int10); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->packer = norm ? rk_pack_vec3_int10_norm : rk_pack_vec3_int10; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_MAT3_FLOAT: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->size = sizeof(rk_mat3_float); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->packer = rk_pack_mat3_float; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_MAT3_INT10: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->size = sizeof(rk_mat3_int10); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     param->packer = norm ? rk_pack_mat3_int10_norm : rk_pack_mat3_int10; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                 default: |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     rk_printf("rk_create_batch(): invalid param format."); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     delete[] batch->params; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     delete batch; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     return nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             packed_size += max_size * param->size; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->commands_size = max_meshes * sizeof(rk_command); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->packed_size = packed_size; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->indices = new rk_ushort[max_size]; |  |  |  |     batch->indices = new rk_ushort[max_size]; | 
			
		
	
		
		
			
				
					
					|  |  |  |     batch->commands = new rk_command[max_meshes]; |  |  |  |     batch->commands = new rk_command[max_meshes]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     batch->params = new rk_parameter[nparams]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glGenVertexArrays(1, &batch->vertex_array); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBindVertexArray(batch->vertex_array); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glGenBuffers(1, &batch->vertices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, batch->vertices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBufferData(GL_ARRAY_BUFFER, vertices->nvertices * vertex_size, vertices->vertices, GL_STATIC_DRAW); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBindBuffer(GL_ARRAY_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glGenBuffers(1, &batch->indices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, batch->indices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertices->nindices * sizeof(rk_ushort), vertices->indices, GL_STATIC_DRAW); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_MultiDrawElementsIndirect) { |  |  |  |     if (rk_MultiDrawElementsIndirect) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         glGenBuffers(1, &batch->commands_buffer); |  |  |  |         glGenBuffers(1, &batch->commands_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer); |  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBufferData(GL_DRAW_INDIRECT_BUFFER, batch->commands_size, nullptr, GL_DYNAMIC_DRAW); |  |  |  |         glBufferData(GL_DRAW_INDIRECT_BUFFER, max_meshes * sizeof(rk_command), nullptr, GL_DYNAMIC_DRAW); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (nparams) { |  |  |  |     if (nparams) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindVertexArray(vertices->array); |  |  |  |         glGenBuffers(1, &batch->params_buffer); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glGenBuffers(1, &batch->params_array); |  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, batch->params_buffer); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, batch->params_array); |  |  |  |         glBufferData(GL_ARRAY_BUFFER, max_size * params_size, nullptr, GL_DYNAMIC_DRAW); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glBufferData(GL_ARRAY_BUFFER, batch->packed_size, nullptr, GL_DYNAMIC_DRAW); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, 0); |  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_parameter const * param = batch->params; |  |  |  |     } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         unsigned binding = RK_PARAMS_BINDING_BASE; |  |  |  |     unsigned binding = 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         unsigned attrib = vertices->layout; |  |  |  |     unsigned attrib = 0; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     unsigned offset = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     glBindVertexBuffer(binding, batch->vertices_buffer, 0, vertex_size); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for (rk_vertex_format const * f = vertices->format; *f; ++f) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         GLboolean const norm = (*f & RK_VERTEX_FORMAT_NORMALIZE) != 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         switch (*f & RK_VERTEX_FORMAT_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 offset += sizeof(rk_vec3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 offset += sizeof(rk_vec3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             case RK_VERTEX_FORMAT_VEC3_UINT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribFormat(attrib, 4, GL_UNSIGNED_INT_2_10_10_10_REV, norm, offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 offset += sizeof(rk_vec3_uint10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                 break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     ++binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     offset = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (nparams) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         rk_parameter * param = batch->params; | 
			
		
	
		
		
			
				
					
					|  |  |  |         for (rk_param_format const * f = params_format; *f; ++f, ++param, ++binding) { |  |  |  |         for (rk_param_format const * f = params_format; *f; ++f, ++param, ++binding) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             bool const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; |  |  |  |             GLboolean const norm = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             glBindVertexBuffer(binding, batch->params_array, param->offset, param->size); |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             switch (*f & RK_PARAM_FORMAT_MASK) { |  |  |  |             switch (*f & RK_PARAM_FORMAT_MASK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_FLOAT: |  |  |  |                 case RK_PARAM_FORMAT_VEC3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->binding = binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->offset = offset; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->size = sizeof(rk_vec3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->packer = rk_pack_vec3_float; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glBindVertexBuffer(binding, batch->params_buffer, param->offset, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, 0); |  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glVertexBindingDivisor(binding, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     offset += max_size * param->size; | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_SHORT: |  |  |  |                 case RK_PARAM_FORMAT_VEC3_SHORT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->binding = binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->offset = offset; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->size = sizeof(rk_vec3_short); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->packer = norm ? rk_pack_vec3_short_norm : rk_pack_vec3_short; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glBindVertexBuffer(binding, batch->params_buffer, param->offset, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 3, GL_SHORT, norm, 0); |  |  |  |                     glVertexAttribFormat(attrib, 3, GL_SHORT, norm, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glVertexBindingDivisor(binding, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     offset += max_size * param->size; | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_VEC3_INT10: |  |  |  |                 case RK_PARAM_FORMAT_VEC3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->binding = binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->offset = offset; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->size = sizeof(rk_vec3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->packer = norm ? rk_pack_vec3_int10_norm : rk_pack_vec3_int10; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glBindVertexBuffer(binding, batch->params_buffer, param->offset, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, 0); |  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glVertexBindingDivisor(binding, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     offset += max_size * param->size; | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_MAT3_FLOAT: |  |  |  |                 case RK_PARAM_FORMAT_MAT3_FLOAT: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->binding = binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->offset = offset; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->size = sizeof(rk_mat3_float); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->packer = rk_pack_mat3_float; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glBindVertexBuffer(binding, batch->params_buffer, param->offset, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offsetof(rk_mat3_float, x)); |  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offsetof(rk_mat3_float, x)); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -592,8 +609,15 @@ rk_batch_t rk_create_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offsetof(rk_mat3_float, z)); |  |  |  |                     glVertexAttribFormat(attrib, 3, GL_FLOAT, GL_FALSE, offsetof(rk_mat3_float, z)); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glVertexBindingDivisor(binding, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     offset += max_size * param->size; | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |                 case RK_PARAM_FORMAT_MAT3_INT10: |  |  |  |                 case RK_PARAM_FORMAT_MAT3_INT10: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->binding = binding; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->offset = offset; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->size = sizeof(rk_mat3_int10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     param->packer = norm ? rk_pack_mat3_int10_norm : rk_pack_mat3_int10; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glBindVertexBuffer(binding, batch->params_buffer, param->offset, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, offsetof(rk_mat3_int10, x)); |  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, offsetof(rk_mat3_int10, x)); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -603,13 +627,14 @@ rk_batch_t rk_create_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glEnableVertexAttribArray(attrib); |  |  |  |                     glEnableVertexAttribArray(attrib); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, offsetof(rk_mat3_int10, z)); |  |  |  |                     glVertexAttribFormat(attrib, 4, GL_INT_2_10_10_10_REV, norm, offsetof(rk_mat3_int10, z)); | 
			
		
	
		
		
			
				
					
					|  |  |  |                     glVertexAttribBinding(attrib++, binding); |  |  |  |                     glVertexAttribBinding(attrib++, binding); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     glVertexBindingDivisor(binding, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |                     offset += max_size * param->size; | 
			
		
	
		
		
			
				
					
					|  |  |  |                     break; |  |  |  |                     break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             glVertexBindingDivisor(binding, 1); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindVertexArray(0); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     return batch; |  |  |  |     glBindVertexArray(0); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return reinterpret_cast<rk_batch_t>(batch); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | void rk_begin_frame() { |  |  |  | void rk_begin_frame() { | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -620,7 +645,6 @@ void rk_select_shader( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_shader_t _shader) { |  |  |  |     rk_shader_t _shader) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_shader * const shader = reinterpret_cast<rk_shader *>(_shader); |  |  |  |     rk_shader * const shader = reinterpret_cast<rk_shader *>(_shader); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (shader) { |  |  |  |     if (shader) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_current_shader = shader; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         glUseProgram(shader->program); |  |  |  |         glUseProgram(shader->program); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -629,7 +653,7 @@ void rk_set_input_float( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_input_t _input, |  |  |  |     rk_input_t _input, | 
			
		
	
		
		
			
				
					
					|  |  |  |     float value) { |  |  |  |     float value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; |  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && input > -1) { |  |  |  |     if (input > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glUniform1f(input, value); |  |  |  |         glUniform1f(input, value); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -638,7 +662,7 @@ void rk_set_input_vec3( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_input_t _input, |  |  |  |     rk_input_t _input, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vec3 const & value) { |  |  |  |     rk_vec3 const & value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; |  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && input > -1) { |  |  |  |     if (input > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glUniform3fv(input, 1, glm::value_ptr(value)); |  |  |  |         glUniform3fv(input, 1, glm::value_ptr(value)); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -647,7 +671,7 @@ void rk_set_input_mat3( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_input_t _input, |  |  |  |     rk_input_t _input, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_mat3 const & value) { |  |  |  |     rk_mat3 const & value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; |  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && input > -1) { |  |  |  |     if (input > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glUniformMatrix3fv(input, 1, GL_FALSE, glm::value_ptr(value)); |  |  |  |         glUniformMatrix3fv(input, 1, GL_FALSE, glm::value_ptr(value)); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -656,7 +680,7 @@ void rk_set_input_mat4( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_input_t _input, |  |  |  |     rk_input_t _input, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_mat4 const & value) { |  |  |  |     rk_mat4 const & value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; |  |  |  |     GLint const input = reinterpret_cast<intptr_t>(_input) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && input > -1) { |  |  |  |     if (input > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glUniformMatrix4fv(input, 1, GL_FALSE, glm::value_ptr(value)); |  |  |  |         glUniformMatrix4fv(input, 1, GL_FALSE, glm::value_ptr(value)); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -665,7 +689,7 @@ void rk_set_param_vec3( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_param_t _param, |  |  |  |     rk_param_t _param, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vec3 const & value) { |  |  |  |     rk_vec3 const & value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const param = reinterpret_cast<intptr_t>(_param) - 1; |  |  |  |     GLint const param = reinterpret_cast<intptr_t>(_param) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && param > -1) { |  |  |  |     if (param > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glVertexAttrib3fv(param, glm::value_ptr(value)); |  |  |  |         glVertexAttrib3fv(param, glm::value_ptr(value)); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -674,7 +698,7 @@ void rk_set_param_mat3( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_param_t _param, |  |  |  |     rk_param_t _param, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_mat3 const & value) { |  |  |  |     rk_mat3 const & value) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const param = reinterpret_cast<intptr_t>(_param) - 1; |  |  |  |     GLint const param = reinterpret_cast<intptr_t>(_param) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_current_shader && param > -1) { |  |  |  |     if (param > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glVertexAttrib3fv(param + 0, glm::value_ptr(value[0])); |  |  |  |         glVertexAttrib3fv(param + 0, glm::value_ptr(value[0])); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glVertexAttrib3fv(param + 1, glm::value_ptr(value[1])); |  |  |  |         glVertexAttrib3fv(param + 1, glm::value_ptr(value[1])); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glVertexAttrib3fv(param + 2, glm::value_ptr(value[2])); |  |  |  |         glVertexAttrib3fv(param + 2, glm::value_ptr(value[2])); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -687,7 +711,7 @@ void rk_select_texture( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_input_t _sampler) { |  |  |  |     rk_input_t _sampler) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_texture const * const texture = reinterpret_cast<rk_texture const *>(_texture); |  |  |  |     rk_texture const * const texture = reinterpret_cast<rk_texture const *>(_texture); | 
			
		
	
		
		
			
				
					
					|  |  |  |     GLint const sampler = reinterpret_cast<intptr_t>(_sampler) - 1; |  |  |  |     GLint const sampler = reinterpret_cast<intptr_t>(_sampler) - 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (texture && sampler > -1 && rk_current_shader) { |  |  |  |     if (texture && sampler > -1) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glActiveTexture(GL_TEXTURE0 + slot); |  |  |  |         glActiveTexture(GL_TEXTURE0 + slot); | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (texture->nlevels) { |  |  |  |         if (texture->nlevels) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             glBindTexture(GL_TEXTURE_2D_ARRAY, texture->texture); |  |  |  |             glBindTexture(GL_TEXTURE_2D_ARRAY, texture->texture); | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -701,24 +725,15 @@ void rk_select_texture( | 
			
		
	
		
		
			
				
					
					|  |  |  | RK_EXPORT void rk_draw_triangles( |  |  |  | RK_EXPORT void rk_draw_triangles( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_triangles_t _triangles) { |  |  |  |     rk_triangles_t _triangles) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_triangles const * const triangles = reinterpret_cast<rk_triangles const *>(_triangles); |  |  |  |     rk_triangles const * const triangles = reinterpret_cast<rk_triangles const *>(_triangles); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (triangles && rk_current_shader && !rk_current_vertices) { |  |  |  |     if (triangles) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glBindVertexArray(triangles->array); |  |  |  |         glBindVertexArray(triangles->array); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glDrawArrays(GL_TRIANGLES, 0, triangles->size); |  |  |  |         glDrawArrays(GL_TRIANGLES, 0, triangles->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindVertexArray(0); |  |  |  |         glBindVertexArray(0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | void rk_select_vertices( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices_t _vertices) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (vertices) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindVertexArray(vertices->array); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_current_vertices = vertices; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static unsigned rk_batch_filter( |  |  |  | static unsigned rk_batch_filter( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_batch & batch, |  |  |  |     rk_batch const & batch, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     unsigned const size, |  |  |  |     unsigned const size, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_instance_flags const * flags) { |  |  |  |     rk_instance_flags const * flags) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_ushort * indices = batch.indices; |  |  |  |     rk_ushort * indices = batch.indices; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -731,7 +746,7 @@ static unsigned rk_batch_filter( | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static unsigned rk_batch_build_commands( |  |  |  | static unsigned rk_batch_build_commands( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_batch & batch, |  |  |  |     rk_batch const & batch, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     unsigned const ninstances, |  |  |  |     unsigned const ninstances, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_mesh const * const meshes) { |  |  |  |     rk_mesh const * const meshes) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_command * const last_command = batch.commands + batch.max_meshes; |  |  |  |     rk_command * const last_command = batch.commands + batch.max_meshes; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -759,7 +774,7 @@ static unsigned rk_batch_build_commands( | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static void rk_batch_pack( |  |  |  | static void rk_batch_pack( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_batch & batch, |  |  |  |     rk_batch const & batch, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     unsigned const ninstances, |  |  |  |     unsigned const ninstances, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_ubyte const ** srcs) { |  |  |  |     rk_ubyte const ** srcs) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_parameter const * const last_param = batch.params + batch.nparams; |  |  |  |     rk_parameter const * const last_param = batch.params + batch.nparams; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -783,29 +798,30 @@ void rk_draw_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_instance_flags const * flags, |  |  |  |     rk_instance_flags const * flags, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_mesh const * meshes, |  |  |  |     rk_mesh const * meshes, | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_ubyte const ** params) { |  |  |  |     rk_ubyte const ** params) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_batch & batch = *reinterpret_cast<rk_batch *>(_batch); |  |  |  |     rk_batch const * const batch = reinterpret_cast<rk_batch const *>(_batch); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     if (!count || count > batch.max_size || !flags || !meshes || !rk_current_shader || !rk_current_vertices) { |  |  |  |     if (!batch || !count || count > batch->max_size || !flags || !meshes) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         return; |  |  |  |         return; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned const ninstances = rk_batch_filter(batch, count, flags); |  |  |  |     unsigned const ninstances = rk_batch_filter(*batch, count, flags); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     if (!ninstances) { |  |  |  |     if (!ninstances) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         return; |  |  |  |         return; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     unsigned const ncommands = rk_batch_build_commands(batch, ninstances, meshes); |  |  |  |     glBindVertexArray(batch->vertex_array); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     unsigned const ncommands = rk_batch_build_commands(*batch, ninstances, meshes); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_MultiDrawElementsIndirect) { |  |  |  |     if (rk_MultiDrawElementsIndirect) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.commands_buffer); |  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch->commands_buffer); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, ncommands * sizeof(rk_command), batch.commands); |  |  |  |         glBufferSubData(GL_DRAW_INDIRECT_BUFFER, 0, ncommands * sizeof(rk_command), batch->commands); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (batch.nparams && params) { |  |  |  |     if (batch->nparams && params) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, batch.params_array); |  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, batch->params_buffer); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         rk_batch_pack(batch, ninstances, params); |  |  |  |         rk_batch_pack(*batch, ninstances, params); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_DrawElementsInstancedBaseInstance) { |  |  |  |     if (rk_DrawElementsInstancedBaseInstance) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (rk_MultiDrawElementsIndirect) { |  |  |  |         if (rk_MultiDrawElementsIndirect) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             rk_MultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, ncommands, sizeof(rk_command)); |  |  |  |             rk_MultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, nullptr, ncommands, sizeof(rk_command)); | 
			
		
	
		
		
			
				
					
					|  |  |  |         } else { |  |  |  |         } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |             rk_command const * const last_command = batch.commands + ncommands; |  |  |  |             rk_command const * const last_command = batch->commands + ncommands; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             for (rk_command const * command = batch.commands; command < last_command; ++command) { |  |  |  |             for (rk_command const * command = batch->commands; command < last_command; ++command) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 rk_DrawElementsInstancedBaseInstance( |  |  |  |                 rk_DrawElementsInstancedBaseInstance( | 
			
		
	
		
		
			
				
					
					|  |  |  |                     GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT, |  |  |  |                     GL_TRIANGLES, command->nvertices, GL_UNSIGNED_SHORT, | 
			
		
	
		
		
			
				
					
					|  |  |  |                     reinterpret_cast<void const *>(command->base_index << 1), |  |  |  |                     reinterpret_cast<void const *>(command->base_index << 1), | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -814,12 +830,11 @@ void rk_draw_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |     } else { | 
			
		
	
		
		
			
				
					
					|  |  |  |         unsigned param_index = 0; |  |  |  |         unsigned param_index = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |         rk_command const * const last_command = batch.commands + ncommands; |  |  |  |         rk_command const * const last_command = batch->commands + ncommands; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         rk_parameter const * const last_param = batch.params + batch.nparams; |  |  |  |         rk_parameter const * const last_param = batch->params + batch->nparams; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         for (rk_command const * command = batch.commands; command < last_command; ++command) { |  |  |  |         for (rk_command const * command = batch->commands; command < last_command; ++command) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             unsigned binding = RK_PARAMS_BINDING_BASE; |  |  |  |             for (rk_parameter const * param = batch->params; param < last_param; ++param) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |             for (rk_parameter const * param = batch.params; param < last_param; ++param, ++binding) { |  |  |  |                 glBindVertexBuffer(param->binding, batch->params_buffer, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 glBindVertexBuffer(binding, batch.params_array, |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                     param->offset + param_index * param->size, param->size); |  |  |  |                     param->offset + param_index * param->size, param->size); | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |             param_index += command->ninstances; |  |  |  |             param_index += command->ninstances; | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -832,14 +847,9 @@ void rk_draw_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rk_MultiDrawElementsIndirect) { |  |  |  |     if (rk_MultiDrawElementsIndirect) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); |  |  |  |         glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (batch.nparams && params) { |  |  |  |     if (batch->nparams && params) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, 0); |  |  |  |         glBindBuffer(GL_ARRAY_BUFFER, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | void rk_unselect_vertices( |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices_t _vertices) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_current_vertices = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glBindVertexArray(0); |  |  |  |     glBindVertexArray(0); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -859,7 +869,6 @@ void rk_unselect_texture( | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | void rk_unselect_shader( |  |  |  | void rk_unselect_shader( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_shader_t _shader) { |  |  |  |     rk_shader_t _shader) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_current_shader = nullptr; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     glUseProgram(0); |  |  |  |     glUseProgram(0); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -877,8 +886,11 @@ void rk_destroy_batch( | 
			
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (batch->nparams) { |  |  |  |         if (batch->nparams) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             delete[] batch->params; |  |  |  |             delete[] batch->params; | 
			
		
	
		
		
			
				
					
					|  |  |  |             glDeleteBuffers(1, &batch->params_array); |  |  |  |             glDeleteBuffers(1, &batch->params_buffer); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         } |  |  |  |         } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         glDeleteBuffers(1, &batch->indices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         glDeleteBuffers(1, &batch->vertices_buffer); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         glDeleteVertexArrays(1, &batch->vertex_array); | 
			
		
	
		
		
			
				
					
					|  |  |  |         delete batch; |  |  |  |         delete batch; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | @ -897,9 +909,9 @@ void rk_destroy_vertices( | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices_t _vertices) { |  |  |  |     rk_vertices_t _vertices) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices); |  |  |  |     rk_vertices * const vertices = reinterpret_cast<rk_vertices *>(_vertices); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (vertices) { |  |  |  |     if (vertices) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         glDeleteBuffers(1, &vertices->indices); |  |  |  |         delete[] vertices->format; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glDeleteBuffers(1, &vertices->vertices); |  |  |  |         delete[] vertices->vertices; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         glDeleteVertexArrays(1, &vertices->array); |  |  |  |         delete[] vertices->indices; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         delete vertices; |  |  |  |         delete vertices; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
	
		
		
			
				
					
					|  |  | 
 |