diff --git a/src/rendering/twn_billboards.c b/src/rendering/twn_billboards.c index 783d367..3d4fa06 100644 --- a/src/rendering/twn_billboards.c +++ b/src/rendering/twn_billboards.c @@ -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 @@ -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); }