support arbitrary count of billboards per batch (in regards to preallocated short index buffer)
This commit is contained in:
		@@ -3,6 +3,7 @@
 | 
			
		||||
#include "twn_engine_context_c.h"
 | 
			
		||||
#include "twn_textures_c.h"
 | 
			
		||||
#include "twn_types.h"
 | 
			
		||||
#include "twn_util_c.h"
 | 
			
		||||
#include "twn_vec.h"
 | 
			
		||||
 | 
			
		||||
#include <stb_ds.h>
 | 
			
		||||
@@ -85,88 +86,93 @@ void finally_draw_billboard_batch(struct MeshBatch const *batch,
 | 
			
		||||
    const Vec2 uv2 = { xr,      yr + hr };
 | 
			
		||||
    const Vec2 uv3 = { xr,      yr      };
 | 
			
		||||
 | 
			
		||||
    /* emit vertex data */
 | 
			
		||||
    VertexBuffer const buffer = get_scratch_vertex_array();
 | 
			
		||||
    VertexBufferBuilder builder = build_vertex_buffer(buffer, sizeof (ElementIndexedBillboard) * primitives_len);
 | 
			
		||||
    for (size_t batch_n = 0; batch_n <= (primitives_len - 1) / QUAD_ELEMENT_BUFFER_LENGTH; batch_n++) {
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < primitives_len; ++i) {
 | 
			
		||||
        struct SpaceBillboard const billboard = ((SpaceBillboard *)(void *)batch->primitives)[i];
 | 
			
		||||
        /* emit vertex data */
 | 
			
		||||
        VertexBuffer const buffer = get_scratch_vertex_array();
 | 
			
		||||
        VertexBufferBuilder builder = build_vertex_buffer(
 | 
			
		||||
            buffer,
 | 
			
		||||
            sizeof (ElementIndexedBillboard) * MIN(primitives_len - batch_n * QUAD_ELEMENT_BUFFER_LENGTH, QUAD_ELEMENT_BUFFER_LENGTH));
 | 
			
		||||
 | 
			
		||||
        /* a = (right + up) * size, b = (right - up) * size*/
 | 
			
		||||
        Vec3 a, b;
 | 
			
		||||
        if (billboard.cylindrical) {
 | 
			
		||||
            a = vec3_mul(right_plus_up_cylindrical, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
            b = vec3_mul(right_minus_up_cylindrical, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
        } else {
 | 
			
		||||
            a = vec3_mul(right_plus_up, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
            b = vec3_mul(right_minus_up, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
        for (size_t i = 0; i < primitives_len; ++i) {
 | 
			
		||||
            struct SpaceBillboard const billboard = ((SpaceBillboard *)(void *)batch->primitives)[batch_n * QUAD_ELEMENT_BUFFER_LENGTH + i];
 | 
			
		||||
 | 
			
		||||
            /* a = (right + up) * size, b = (right - up) * size*/
 | 
			
		||||
            Vec3 a, b;
 | 
			
		||||
            if (billboard.cylindrical) {
 | 
			
		||||
                a = vec3_mul(right_plus_up_cylindrical, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
                b = vec3_mul(right_minus_up_cylindrical, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
            } else {
 | 
			
		||||
                a = vec3_mul(right_plus_up, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
                b = vec3_mul(right_minus_up, ((Vec3){billboard.size.x, billboard.size.y, billboard.size.x }));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            struct ElementIndexedBillboard const payload = {
 | 
			
		||||
                /* TODO: use the flat shading to not set two of the colors */
 | 
			
		||||
                .c0 = billboard.color,
 | 
			
		||||
                .c1 = billboard.color,
 | 
			
		||||
                .c2 = billboard.color,
 | 
			
		||||
                .c3 = billboard.color,
 | 
			
		||||
 | 
			
		||||
                .uv0 = uv0,
 | 
			
		||||
                .uv1 = uv1,
 | 
			
		||||
                .uv2 = uv2,
 | 
			
		||||
                .uv3 = uv3,
 | 
			
		||||
 | 
			
		||||
                .v0 = vec3_sub(billboard.position, b),
 | 
			
		||||
                .v1 = vec3_sub(billboard.position, a),
 | 
			
		||||
                .v2 = vec3_add(billboard.position, b),
 | 
			
		||||
                .v3 = vec3_add(billboard.position, a),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            push_to_vertex_buffer_builder(&builder, &payload, sizeof (payload));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        struct ElementIndexedBillboard const payload = {
 | 
			
		||||
            /* TODO: use the flat shading to not set two of the colors */
 | 
			
		||||
            .c0 = billboard.color,
 | 
			
		||||
            .c1 = billboard.color,
 | 
			
		||||
            .c2 = billboard.color,
 | 
			
		||||
            .c3 = billboard.color,
 | 
			
		||||
        /* commit to drawing */
 | 
			
		||||
        DeferredCommandDraw command = {0};
 | 
			
		||||
 | 
			
		||||
            .uv0 = uv0,
 | 
			
		||||
            .uv1 = uv1,
 | 
			
		||||
            .uv2 = uv2,
 | 
			
		||||
            .uv3 = uv3,
 | 
			
		||||
 | 
			
		||||
            .v0 = vec3_sub(billboard.position, b),
 | 
			
		||||
            .v1 = vec3_sub(billboard.position, a),
 | 
			
		||||
            .v2 = vec3_add(billboard.position, b),
 | 
			
		||||
            .v3 = vec3_add(billboard.position, a),
 | 
			
		||||
        command.vertices = (AttributeArrayPointer) {
 | 
			
		||||
            .arity = 3,
 | 
			
		||||
            .type = GL_FLOAT,
 | 
			
		||||
            .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
            .offset = offsetof(ElementIndexedBillboard, v0),
 | 
			
		||||
            .buffer = buffer
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        push_to_vertex_buffer_builder(&builder, &payload, sizeof (payload));
 | 
			
		||||
        command.texcoords = (AttributeArrayPointer) {
 | 
			
		||||
            .arity = 2,
 | 
			
		||||
            .type = GL_FLOAT,
 | 
			
		||||
            .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
            .offset = offsetof(ElementIndexedBillboard, uv0),
 | 
			
		||||
            .buffer = buffer
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        command.colors = (AttributeArrayPointer) {
 | 
			
		||||
            .arity = 4,
 | 
			
		||||
            .type = GL_UNSIGNED_BYTE,
 | 
			
		||||
            .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
            .offset = offsetof(ElementIndexedBillboard, c0),
 | 
			
		||||
            .buffer = buffer
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        command.textured = true;
 | 
			
		||||
        command.texture_key = texture_key;
 | 
			
		||||
 | 
			
		||||
        command.element_buffer = get_quad_element_buffer();
 | 
			
		||||
        command.element_count = 6 * (GLsizei)primitives_len;
 | 
			
		||||
        command.range_end = 6 * (GLsizei)primitives_len;
 | 
			
		||||
 | 
			
		||||
        /* TODO: support alpha blended case, with distance sort */
 | 
			
		||||
        TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
 | 
			
		||||
        if (mode == TEXTURE_MODE_GHOSTLY)
 | 
			
		||||
            mode = TEXTURE_MODE_SEETHROUGH;
 | 
			
		||||
        use_texture_mode(mode);
 | 
			
		||||
 | 
			
		||||
        DeferredCommand final_command = {
 | 
			
		||||
            .type = DEFERRED_COMMAND_TYPE_DRAW,
 | 
			
		||||
            .draw = command
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        arrpush(deferred_commands, final_command);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* commit to drawing */
 | 
			
		||||
    DeferredCommandDraw command = {0};
 | 
			
		||||
 | 
			
		||||
    command.vertices = (AttributeArrayPointer) {
 | 
			
		||||
        .arity = 3,
 | 
			
		||||
        .type = GL_FLOAT,
 | 
			
		||||
        .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
        .offset = offsetof(ElementIndexedBillboard, v0),
 | 
			
		||||
        .buffer = buffer
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    command.texcoords = (AttributeArrayPointer) {
 | 
			
		||||
        .arity = 2,
 | 
			
		||||
        .type = GL_FLOAT,
 | 
			
		||||
        .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
        .offset = offsetof(ElementIndexedBillboard, uv0),
 | 
			
		||||
        .buffer = buffer
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    command.colors = (AttributeArrayPointer) {
 | 
			
		||||
        .arity = 4,
 | 
			
		||||
        .type = GL_UNSIGNED_BYTE,
 | 
			
		||||
        .stride = offsetof(ElementIndexedBillboard, v1),
 | 
			
		||||
        .offset = offsetof(ElementIndexedBillboard, c0),
 | 
			
		||||
        .buffer = buffer
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    command.textured = true;
 | 
			
		||||
    command.texture_key = texture_key;
 | 
			
		||||
 | 
			
		||||
    command.element_buffer = get_quad_element_buffer();
 | 
			
		||||
    command.element_count = 6 * (GLsizei)primitives_len;
 | 
			
		||||
    command.range_end = 6 * (GLsizei)primitives_len;
 | 
			
		||||
 | 
			
		||||
    /* TODO: support alpha blended case, with distance sort */
 | 
			
		||||
    TextureMode mode = textures_get_mode(&ctx.texture_cache, texture_key);
 | 
			
		||||
    if (mode == TEXTURE_MODE_GHOSTLY)
 | 
			
		||||
        mode = TEXTURE_MODE_SEETHROUGH;
 | 
			
		||||
    use_texture_mode(mode);
 | 
			
		||||
 | 
			
		||||
    DeferredCommand final_command = {
 | 
			
		||||
        .type = DEFERRED_COMMAND_TYPE_DRAW,
 | 
			
		||||
        .draw = command
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    arrpush(deferred_commands, final_command);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user