Custom instance parameters.
This commit is contained in:
		@ -33,9 +33,6 @@ static void rk_debug_message_callback(
 | 
			
		||||
    GLsizei length,
 | 
			
		||||
    GLchar const * message,
 | 
			
		||||
    void const * userParam) {
 | 
			
		||||
    if (id == 131169 || id == 131185 || id == 131218 || id == 131204) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    printf("[RK_ENGINE][GL] (id=%d) %s\n", id, message);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -52,15 +49,8 @@ rk_window_t rk_initialize(
 | 
			
		||||
        GLubyte const * const language = glGetString(GL_SHADING_LANGUAGE_VERSION);
 | 
			
		||||
        printf("[RK_ENGINE] version: %s, language: %s\n", version, language);
 | 
			
		||||
 | 
			
		||||
        GLint context_flags = 0;
 | 
			
		||||
        glGetIntegerv(GL_CONTEXT_FLAGS, &context_flags);
 | 
			
		||||
        if (context_flags & GL_CONTEXT_FLAG_DEBUG_BIT) {
 | 
			
		||||
            printf("[RK_ENGINE] Debug context enabled\n");
 | 
			
		||||
            glDebugMessageCallback(rk_debug_message_callback, nullptr);
 | 
			
		||||
            glEnable(GL_DEBUG_OUTPUT);
 | 
			
		||||
        } else {
 | 
			
		||||
            glDisable(GL_DEBUG_OUTPUT);
 | 
			
		||||
        }
 | 
			
		||||
        glDebugMessageCallback(rk_debug_message_callback, nullptr);
 | 
			
		||||
        glEnable(GL_DEBUG_OUTPUT);
 | 
			
		||||
 | 
			
		||||
        glDisable(GL_BLEND);
 | 
			
		||||
        glEnable(GL_DITHER);
 | 
			
		||||
@ -93,7 +83,6 @@ static void rk_print_program_infolog(GLuint program) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO: external loading of shader sources
 | 
			
		||||
//TODO: error handling
 | 
			
		||||
rk_shader_t rk_load_shader(
 | 
			
		||||
    rk_uint const vert_nlines,
 | 
			
		||||
@ -104,11 +93,11 @@ rk_shader_t rk_load_shader(
 | 
			
		||||
    shader->vertex = glCreateShader(GL_VERTEX_SHADER);
 | 
			
		||||
    shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
 | 
			
		||||
    shader->program = glCreateProgram();
 | 
			
		||||
    if (vert_nlines == 0 || vert_lines == nullptr) {
 | 
			
		||||
    if (!vert_nlines || !vert_lines) {
 | 
			
		||||
        rk_printf("Missing vertex shader.");
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    if (frag_nlines == 0 || frag_lines == nullptr) {
 | 
			
		||||
    if (!frag_nlines || !frag_lines) {
 | 
			
		||||
        rk_printf("Missing fragment shader.");
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
@ -357,8 +346,6 @@ rk_vertices_t rk_create_vertices(
 | 
			
		||||
                glVertexAttribFormat(vertices->layout, 4, GL_UNSIGNED_INT_2_10_10_10_REV, normalize, offset);
 | 
			
		||||
                offset += sizeof(rk_uint);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        glVertexAttribBinding(vertices->layout, RK_VERTICES_BINDING);
 | 
			
		||||
    }
 | 
			
		||||
@ -370,84 +357,120 @@ rk_vertices_t rk_create_vertices(
 | 
			
		||||
    return vertices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO: support for mat3 orientations with packing into int10 * 3
 | 
			
		||||
// - maybe from quaternions inputs
 | 
			
		||||
// - maybe it's possible to implement efficient quaternions in glsl?
 | 
			
		||||
static rk_uint rk_convert_vec3_float(
 | 
			
		||||
    rk_ubyte * const dst,
 | 
			
		||||
    rk_ubyte const * const src,
 | 
			
		||||
    rk_ushort const idx) {
 | 
			
		||||
    *reinterpret_cast<rk_vec3 *>(dst) = reinterpret_cast<rk_vec3 const *>(src)[idx];
 | 
			
		||||
    return sizeof(rk_vec3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static rk_uint rk_convert_vec3_short(
 | 
			
		||||
    rk_ubyte * const _dst,
 | 
			
		||||
    rk_ubyte const * const _src,
 | 
			
		||||
    rk_ushort const idx) {
 | 
			
		||||
    rk_vec3_short * const dst = reinterpret_cast<rk_vec3_short *>(_dst);
 | 
			
		||||
    rk_vec3 const & src = reinterpret_cast<rk_vec3 const *>(_src)[idx];
 | 
			
		||||
    dst->x = static_cast<rk_short>(src.x);
 | 
			
		||||
    dst->y = static_cast<rk_short>(src.y);
 | 
			
		||||
    dst->z = static_cast<rk_short>(src.z);
 | 
			
		||||
    return sizeof(rk_vec3_short);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static rk_uint rk_convert_vec3_short_normalize(
 | 
			
		||||
    rk_ubyte * const _dst,
 | 
			
		||||
    rk_ubyte const * const _src,
 | 
			
		||||
    rk_ushort const idx) {
 | 
			
		||||
    rk_vec3_short * const dst = reinterpret_cast<rk_vec3_short *>(_dst);
 | 
			
		||||
    rk_vec3 const & src = reinterpret_cast<rk_vec3 const *>(_src)[idx];
 | 
			
		||||
    #define _convert(s) (static_cast<rk_short>((s) * ((s) < 0.f ? 32768.f : 32767.f)))
 | 
			
		||||
    dst->x = _convert(src.x);
 | 
			
		||||
    dst->y = _convert(src.y);
 | 
			
		||||
    dst->z = _convert(src.z);
 | 
			
		||||
    #undef _convert
 | 
			
		||||
    return sizeof(rk_vec3_short);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static rk_uint rk_convert_vec3_int10(
 | 
			
		||||
    rk_ubyte * const dst,
 | 
			
		||||
    rk_ubyte const * const _src,
 | 
			
		||||
    rk_ushort const idx) {
 | 
			
		||||
    rk_vec3 const & src = reinterpret_cast<rk_vec3 const *>(_src)[idx];
 | 
			
		||||
    #define _convert(s) (static_cast<rk_int>((s) * ((s) < 0.f ? 512.f : 511.f)) & 1023)
 | 
			
		||||
    *reinterpret_cast<rk_int *>(dst) = _convert(src.x) | (_convert(src.y) << 10) | (_convert(src.z) << 20);
 | 
			
		||||
    #undef _convert
 | 
			
		||||
    return sizeof(rk_int);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rk_batch_t rk_create_batch(
 | 
			
		||||
    rk_uint max_size,
 | 
			
		||||
    rk_batch_translation_format translation_format,
 | 
			
		||||
    rk_batch_orientation_format orientation_format) {
 | 
			
		||||
    if (!max_size || max_size > RK_BATCH_MAX_SIZE || !rk_current_shader || !rk_current_vertices) {
 | 
			
		||||
    rk_param_format const * params_format) {
 | 
			
		||||
    if (!max_size || !params_format || max_size > RK_BATCH_MAX_SIZE || !rk_current_shader || !rk_current_vertices) {
 | 
			
		||||
        rk_printf("rk_create_batch(): invalid parameters.");
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    rk_uint translation_size = 0;
 | 
			
		||||
    switch (translation_format) {
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
			
		||||
            translation_size = sizeof(rk_translation_float);
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
			
		||||
            translation_size = sizeof(rk_translation_short);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            rk_printf("rk_create_batch(): invalid translation format.");
 | 
			
		||||
            return nullptr;
 | 
			
		||||
            break;
 | 
			
		||||
    rk_uint nparams = 0;
 | 
			
		||||
    rk_uint params_size = 0;
 | 
			
		||||
    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);
 | 
			
		||||
                break;
 | 
			
		||||
            case RK_PARAM_FORMAT_VEC3_SHORT:
 | 
			
		||||
                params_size += sizeof(rk_vec3_short);
 | 
			
		||||
                break;
 | 
			
		||||
            case RK_PARAM_FORMAT_VEC3_INT10:
 | 
			
		||||
                params_size += sizeof(rk_int);
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                rk_printf("rk_create_batch(): invalid param format.");
 | 
			
		||||
                return nullptr;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    rk_uint orientation_size = 0;
 | 
			
		||||
    switch (orientation_format) {
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
			
		||||
            orientation_size = 0;
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
			
		||||
            orientation_size = sizeof(rk_orientation_float);
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
			
		||||
            orientation_size = sizeof(rk_orientation_int10);
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            rk_printf("rk_create_batch(): invalid orientation format.");
 | 
			
		||||
            return nullptr;
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    rk_uint const params_size = translation_size + orientation_size;
 | 
			
		||||
    rk_batch * batch = new rk_batch;
 | 
			
		||||
    batch->size = max_size;
 | 
			
		||||
    batch->translation_format = translation_format;
 | 
			
		||||
    batch->orientation_format = orientation_format;
 | 
			
		||||
    batch->nparams = nparams;
 | 
			
		||||
    batch->params_size = params_size;
 | 
			
		||||
    batch->indices = new rk_ushort[batch->size];
 | 
			
		||||
    batch->params = new rk_ubyte[batch->size * params_size];
 | 
			
		||||
    batch->commands = new rk_command[batch->size * sizeof(rk_command)];
 | 
			
		||||
    glGenBuffers(1, &batch->params_buffer);
 | 
			
		||||
    rk_uint const translation_layout = rk_current_vertices->layout;
 | 
			
		||||
    glEnableVertexAttribArray(translation_layout);
 | 
			
		||||
    switch (translation_format) {
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
			
		||||
            glVertexAttribFormat(translation_layout, 3, GL_FLOAT, GL_FALSE, 0);
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
			
		||||
            glVertexAttribFormat(translation_layout, 3, GL_SHORT, GL_FALSE, 0);
 | 
			
		||||
            break;
 | 
			
		||||
    batch->indices = new rk_ushort[max_size];
 | 
			
		||||
    batch->commands = new rk_command[max_size * sizeof(rk_command)];
 | 
			
		||||
    if (nparams) {
 | 
			
		||||
        batch->converters = new rk_param_converter[nparams];
 | 
			
		||||
        batch->params = new rk_ubyte[max_size * params_size];
 | 
			
		||||
        glGenBuffers(1, &batch->params_buffer);
 | 
			
		||||
        rk_uint layout = rk_current_vertices->layout;
 | 
			
		||||
        rk_param_converter * converter = batch->converters;
 | 
			
		||||
        rk_uint offset = 0;
 | 
			
		||||
        for (rk_param_format const * f = params_format; *f; ++f, ++layout, ++converter) {
 | 
			
		||||
            GLboolean const normalize = (*f & RK_PARAM_FORMAT_NORMALIZE) != 0;
 | 
			
		||||
            glEnableVertexAttribArray(layout);
 | 
			
		||||
            switch (*f & RK_PARAM_FORMAT_MASK) {
 | 
			
		||||
                case RK_PARAM_FORMAT_VEC3_FLOAT:
 | 
			
		||||
                    glVertexAttribFormat(layout, 3, GL_FLOAT, normalize, offset);
 | 
			
		||||
                    *converter = rk_convert_vec3_float;
 | 
			
		||||
                    offset += sizeof(rk_vec3);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_PARAM_FORMAT_VEC3_SHORT:
 | 
			
		||||
                    glVertexAttribFormat(layout, 3, GL_SHORT, normalize, offset);
 | 
			
		||||
                    if (normalize) {
 | 
			
		||||
                        *converter = rk_convert_vec3_short_normalize;
 | 
			
		||||
                    }
 | 
			
		||||
                    else {
 | 
			
		||||
                        *converter = rk_convert_vec3_short;
 | 
			
		||||
                    }
 | 
			
		||||
                    offset += sizeof(rk_vec3_short);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_PARAM_FORMAT_VEC3_INT10:
 | 
			
		||||
                    glVertexAttribFormat(layout, 4, GL_INT_2_10_10_10_REV, normalize, offset);
 | 
			
		||||
                    *converter = rk_convert_vec3_int10;
 | 
			
		||||
                    offset += sizeof(rk_int);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            glVertexAttribBinding(layout, RK_PARAMS_BINDING);
 | 
			
		||||
        }
 | 
			
		||||
        glVertexBindingDivisor(RK_PARAMS_BINDING, 1);
 | 
			
		||||
        glBindVertexBuffer(RK_PARAMS_BINDING, batch->params_buffer, 0, batch->params_size);
 | 
			
		||||
    }
 | 
			
		||||
    glVertexAttribBinding(translation_layout, RK_PARAMS_BINDING);
 | 
			
		||||
    rk_uint const orientation_layout = rk_current_vertices->layout + 1;
 | 
			
		||||
    switch (orientation_format) {
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
			
		||||
            glEnableVertexAttribArray(orientation_layout);
 | 
			
		||||
            glVertexAttribFormat(orientation_layout, 3, GL_FLOAT, GL_FALSE, translation_size);
 | 
			
		||||
            glVertexAttribBinding(orientation_layout, RK_PARAMS_BINDING);
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
			
		||||
            glEnableVertexAttribArray(orientation_layout);
 | 
			
		||||
            glVertexAttribFormat(orientation_layout, GL_BGRA, GL_INT_2_10_10_10_REV, GL_TRUE, translation_size);
 | 
			
		||||
            glVertexAttribBinding(orientation_layout, RK_PARAMS_BINDING);
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    glVertexBindingDivisor(RK_PARAMS_BINDING, 1);
 | 
			
		||||
    glBindVertexBuffer(RK_PARAMS_BINDING, batch->params_buffer, 0, batch->params_size);
 | 
			
		||||
    if (rk_MultiDrawElementsIndirect) {
 | 
			
		||||
        glGenBuffers(1, &batch->commands_buffer);
 | 
			
		||||
    }
 | 
			
		||||
@ -493,6 +516,24 @@ void rk_select_vertices(
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
rk_param_t rk_resolve_param(
 | 
			
		||||
    char const * name) {
 | 
			
		||||
    if (!rk_current_shader || !name) {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
    GLint const location = glGetAttribLocation(rk_current_shader->program, name);
 | 
			
		||||
    return reinterpret_cast<rk_param_t>(location + 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rk_set_param_vec3(
 | 
			
		||||
    rk_param_t param,
 | 
			
		||||
    rk_vec3 const & value) {
 | 
			
		||||
    GLint const location = reinterpret_cast<intptr_t>(param) - 1;
 | 
			
		||||
    if (rk_current_shader && location > -1) {
 | 
			
		||||
        glVertexAttrib3fv(location, glm::value_ptr(value));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static rk_uint rk_batch_filter(
 | 
			
		||||
    rk_uint const size,
 | 
			
		||||
    rk_ushort * const _indices,
 | 
			
		||||
@ -534,32 +575,18 @@ static rk_uint rk_batch_build_commands(
 | 
			
		||||
    return commands - _commands;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template < typename _instance_params_t >
 | 
			
		||||
static void rk_batch_convert_params(
 | 
			
		||||
    rk_batch & batch,
 | 
			
		||||
    rk_uint const count,
 | 
			
		||||
    rk_ushort const * const _indices,
 | 
			
		||||
    rk_ubyte * const _params,
 | 
			
		||||
    rk_vec3 const * const translations,
 | 
			
		||||
    rk_vec3 const * const orientations) {
 | 
			
		||||
    _instance_params_t * params = reinterpret_cast<_instance_params_t *>(_params);
 | 
			
		||||
    rk_ushort const * const last = _indices + count;
 | 
			
		||||
    for (rk_ushort const * indices = _indices; indices < last; ++indices, ++params) {
 | 
			
		||||
        rk_uint const index = *indices;
 | 
			
		||||
        params->set(translations[index], orientations[index]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template < typename _instance_params_t >
 | 
			
		||||
static void rk_batch_convert_params(
 | 
			
		||||
    rk_uint const count,
 | 
			
		||||
    rk_ushort const * const _indices,
 | 
			
		||||
    rk_ubyte * const _params,
 | 
			
		||||
    rk_vec3 const * const translations) {
 | 
			
		||||
    _instance_params_t * params = reinterpret_cast<_instance_params_t *>(_params);
 | 
			
		||||
    rk_ushort const * const last = _indices + count;
 | 
			
		||||
    for (rk_ushort const * indices = _indices; indices < last; ++indices, ++params) {
 | 
			
		||||
        rk_uint const index = *indices;
 | 
			
		||||
        params->set(translations[index]);
 | 
			
		||||
    rk_ubyte const ** const params) {
 | 
			
		||||
    rk_ubyte * dst = batch.params;
 | 
			
		||||
    rk_ushort const * const last_index = batch.indices + count;
 | 
			
		||||
    rk_ubyte const ** const last_param = params + batch.nparams;
 | 
			
		||||
    for (rk_ushort const * index = batch.indices; index < last_index; ++index) {
 | 
			
		||||
        rk_param_converter const * converter = batch.converters;
 | 
			
		||||
        for (rk_ubyte const ** src = params; src < last_param; ++src, ++converter) {
 | 
			
		||||
            dst += (*converter)(dst, *src, *index);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -568,14 +595,9 @@ void rk_draw_batch(
 | 
			
		||||
    rk_uint size,
 | 
			
		||||
    rk_instance_flags const * flags,
 | 
			
		||||
    rk_mesh const * meshes,
 | 
			
		||||
    rk_vec3 const * translations,
 | 
			
		||||
    rk_vec3 const * orientations) {
 | 
			
		||||
    rk_ubyte const ** params) {
 | 
			
		||||
    rk_batch & batch = *reinterpret_cast<rk_batch *>(_batch);
 | 
			
		||||
    if (!size || size > batch.size || !flags || !meshes || !translations ||
 | 
			
		||||
        !rk_current_shader || !rk_current_vertices) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (batch.orientation_format != RK_BATCH_ORIENTATION_FORMAT_NONE && !orientations) {
 | 
			
		||||
    if (!size || size > batch.size || !flags || !meshes || !rk_current_shader || !rk_current_vertices) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    rk_uint const count = rk_batch_filter(size, batch.indices, flags);
 | 
			
		||||
@ -587,46 +609,11 @@ void rk_draw_batch(
 | 
			
		||||
        glBindBuffer(GL_DRAW_INDIRECT_BUFFER, batch.commands_buffer);
 | 
			
		||||
        glBufferData(GL_DRAW_INDIRECT_BUFFER, ncommands * sizeof(rk_command), batch.commands, GL_STREAM_DRAW);
 | 
			
		||||
    }
 | 
			
		||||
    switch (batch.translation_format) {
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_FLOAT:
 | 
			
		||||
            switch (batch.orientation_format) {
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
			
		||||
                    rk_batch_convert_params<rk_translation_float>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
			
		||||
                    rk_batch_convert_params<rk_params_float_float>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations, orientations);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
			
		||||
                    rk_batch_convert_params<rk_params_float_int10>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations, orientations);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case RK_BATCH_TRANSLATION_FORMAT_SHORT:
 | 
			
		||||
            switch (batch.orientation_format) {
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_NONE:
 | 
			
		||||
                    rk_batch_convert_params<rk_translation_short>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_FLOAT:
 | 
			
		||||
                    rk_batch_convert_params<rk_params_short_float>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations, orientations);
 | 
			
		||||
                    break;
 | 
			
		||||
                case RK_BATCH_ORIENTATION_FORMAT_INT10:
 | 
			
		||||
                    rk_batch_convert_params<rk_params_short_int10>(
 | 
			
		||||
                        count, batch.indices, batch.params, translations, orientations);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    glBindBuffer(GL_ARRAY_BUFFER, batch.params_buffer);
 | 
			
		||||
    glBufferData(GL_ARRAY_BUFFER, count * batch.params_size, batch.params, GL_STREAM_DRAW);
 | 
			
		||||
    glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
			
		||||
    if (batch.orientation_format == RK_BATCH_ORIENTATION_FORMAT_NONE) {
 | 
			
		||||
        rk_vec3 const forward(0.f, 1.f, 0.f);
 | 
			
		||||
        glVertexAttrib3fv(rk_current_vertices->layout + 1, glm::value_ptr(forward));
 | 
			
		||||
    if (batch.nparams) {
 | 
			
		||||
        rk_batch_convert_params(batch, count, params);
 | 
			
		||||
        glBindBuffer(GL_ARRAY_BUFFER, batch.params_buffer);
 | 
			
		||||
        glBufferData(GL_ARRAY_BUFFER, count * batch.params_size, batch.params, GL_STREAM_DRAW);
 | 
			
		||||
        glBindBuffer(GL_ARRAY_BUFFER, 0);
 | 
			
		||||
    }
 | 
			
		||||
    if (rk_DrawElementsInstancedBaseInstance) {
 | 
			
		||||
        if (rk_MultiDrawElementsIndirect) {
 | 
			
		||||
@ -645,8 +632,10 @@ void rk_draw_batch(
 | 
			
		||||
        rk_uint params_offset = 0;
 | 
			
		||||
        rk_command const * const last_command = batch.commands + ncommands;
 | 
			
		||||
        for (rk_command const * command = batch.commands; command < last_command; ++command) {
 | 
			
		||||
            glBindVertexBuffer(RK_PARAMS_BINDING, batch.params_buffer, params_offset, batch.params_size);
 | 
			
		||||
            params_offset += command->ninstances * batch.params_size;
 | 
			
		||||
            if (batch.nparams) {
 | 
			
		||||
                glBindVertexBuffer(RK_PARAMS_BINDING, batch.params_buffer, params_offset, batch.params_size);
 | 
			
		||||
                params_offset += command->ninstances * batch.params_size;
 | 
			
		||||
            }
 | 
			
		||||
            glDrawElementsInstanced(
 | 
			
		||||
                GL_TRIANGLES, command->count, GL_UNSIGNED_SHORT,
 | 
			
		||||
                reinterpret_cast<void const *>(command->base_index << 1),
 | 
			
		||||
@ -689,9 +678,12 @@ void rk_destroy_batch(
 | 
			
		||||
    rk_batch * const batch = reinterpret_cast<rk_batch *>(_batch);
 | 
			
		||||
    if (batch) {
 | 
			
		||||
        delete[] batch->indices;
 | 
			
		||||
        delete[] batch->params;
 | 
			
		||||
        delete[] batch->commands;
 | 
			
		||||
        glDeleteBuffers(1, &batch->params_buffer);
 | 
			
		||||
        if (batch->nparams) {
 | 
			
		||||
            delete[] batch->converters;
 | 
			
		||||
            delete[] batch->params;
 | 
			
		||||
            glDeleteBuffers(1, &batch->params_buffer);
 | 
			
		||||
        }
 | 
			
		||||
        if (rk_MultiDrawElementsIndirect) {
 | 
			
		||||
            glDeleteBuffers(1, &batch->commands_buffer);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,8 @@ struct rk_vertices {
 | 
			
		||||
    GLuint indices;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef rk_uint (*rk_param_converter)(rk_ubyte * const, rk_ubyte const * const, rk_ushort const);
 | 
			
		||||
 | 
			
		||||
struct rk_command {
 | 
			
		||||
    GLuint count;
 | 
			
		||||
    GLuint ninstances;
 | 
			
		||||
@ -64,70 +66,21 @@ struct rk_command {
 | 
			
		||||
 | 
			
		||||
struct rk_batch {
 | 
			
		||||
    rk_uint size;
 | 
			
		||||
    rk_batch_translation_format translation_format;
 | 
			
		||||
    rk_batch_orientation_format orientation_format;
 | 
			
		||||
    rk_uint nparams;
 | 
			
		||||
    rk_uint params_size;
 | 
			
		||||
    rk_ushort * indices;
 | 
			
		||||
    rk_ubyte * params;
 | 
			
		||||
    rk_command * commands;
 | 
			
		||||
    rk_param_converter * converters;
 | 
			
		||||
    rk_ubyte * params;
 | 
			
		||||
    GLuint params_buffer;
 | 
			
		||||
    GLuint commands_buffer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rk_translation_float {
 | 
			
		||||
    rk_vec3 xyz;
 | 
			
		||||
 | 
			
		||||
    inline void set(rk_vec3 const & translation) {
 | 
			
		||||
        xyz = translation;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rk_translation_short {
 | 
			
		||||
struct rk_vec3_short {
 | 
			
		||||
    rk_short x;
 | 
			
		||||
    rk_short y;
 | 
			
		||||
    rk_short z;
 | 
			
		||||
    rk_short pad;
 | 
			
		||||
 | 
			
		||||
    inline void set(rk_vec3 const & translation) {
 | 
			
		||||
        x = static_cast<rk_short>(translation.x);
 | 
			
		||||
        y = static_cast<rk_short>(translation.y);
 | 
			
		||||
        z = static_cast<rk_short>(translation.z);
 | 
			
		||||
        pad = 0;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rk_orientation_float {
 | 
			
		||||
    rk_vec3 xyz;
 | 
			
		||||
 | 
			
		||||
    inline void set(rk_vec3 const & orientation) {
 | 
			
		||||
        xyz = orientation;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct rk_orientation_int10 {
 | 
			
		||||
    rk_uint xyz;
 | 
			
		||||
 | 
			
		||||
    inline void set(rk_vec3 const & orientation) {
 | 
			
		||||
        #define _pack_10(x) static_cast<rk_uint>(static_cast<rk_int>((x) * ((x) < 0.f ? 512.f : 511.f)) & 1023)
 | 
			
		||||
        xyz = _pack_10(orientation.x) << 20 | _pack_10(orientation.y) << 10 | _pack_10(orientation.z);
 | 
			
		||||
        #undef _pack_10
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template < typename _translation_t, typename _orientation_t >
 | 
			
		||||
struct rk_params {
 | 
			
		||||
    _translation_t translation;
 | 
			
		||||
    _orientation_t orientation;
 | 
			
		||||
 | 
			
		||||
    inline void set(rk_vec3 const & translation, rk_vec3 const & orientation) {
 | 
			
		||||
        this->translation.set(translation);
 | 
			
		||||
        this->orientation.set(orientation);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef rk_params<rk_translation_float, rk_orientation_float> rk_params_float_float;
 | 
			
		||||
typedef rk_params<rk_translation_float, rk_orientation_int10> rk_params_float_int10;
 | 
			
		||||
typedef rk_params<rk_translation_short, rk_orientation_float> rk_params_short_float;
 | 
			
		||||
typedef rk_params<rk_translation_short, rk_orientation_int10> rk_params_short_int10;
 | 
			
		||||
 | 
			
		||||
#endif // _RK_ENGINE_RENDER_OPENGLES_H
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user