mirror of https://github.com/bjornbytes/lovr.git
Super ultra cool geometry cache;
Pass stores a small 16-bucket cache of vertices/indices it recently generated. Draws that have relatively predictable geometry can provide a hash along with their draw. The Pass will reuse vertices based on the hash, when possible, and return a NULL vertex pointer to let the draw-er know they don't need to generate any vertices. This provides a dramatic speedup when drawing the same shape many times in a row. The overhead is negligible, with benefits kicking in with just a small handful of repeated draws (3-5 for cubes, less for more complex shapes).
This commit is contained in:
parent
ae87abc7bb
commit
4e92a4e503
|
@ -26,6 +26,7 @@ const char** os_vk_get_instance_extensions(uint32_t* count);
|
||||||
#define MAX_FRAME_MEMORY (1 << 30)
|
#define MAX_FRAME_MEMORY (1 << 30)
|
||||||
#define MAX_SHADER_RESOURCES 32
|
#define MAX_SHADER_RESOURCES 32
|
||||||
#define MATERIALS_PER_BLOCK 1024
|
#define MATERIALS_PER_BLOCK 1024
|
||||||
|
#define FLOAT_BITS(f) ((union { float f; uint32_t u; }) { f }).u
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct { float x, y, z; } position;
|
struct { float x, y, z; } position;
|
||||||
|
@ -170,6 +171,7 @@ typedef enum {
|
||||||
} VertexFormat;
|
} VertexFormat;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint64_t hash;
|
||||||
VertexMode mode;
|
VertexMode mode;
|
||||||
DefaultShader shader;
|
DefaultShader shader;
|
||||||
Material* material;
|
Material* material;
|
||||||
|
@ -178,14 +180,11 @@ typedef struct {
|
||||||
Buffer* buffer;
|
Buffer* buffer;
|
||||||
VertexFormat format;
|
VertexFormat format;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
const void* data;
|
|
||||||
void** pointer;
|
void** pointer;
|
||||||
} vertex;
|
} vertex;
|
||||||
struct {
|
struct {
|
||||||
Buffer* buffer;
|
Buffer* buffer;
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
uint32_t stride;
|
|
||||||
const void* data;
|
|
||||||
void** pointer;
|
void** pointer;
|
||||||
} index;
|
} index;
|
||||||
uint32_t start;
|
uint32_t start;
|
||||||
|
@ -244,6 +243,23 @@ typedef struct {
|
||||||
bool dirty;
|
bool dirty;
|
||||||
} Pipeline;
|
} Pipeline;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SHAPE_PLANE,
|
||||||
|
SHAPE_BOX,
|
||||||
|
SHAPE_CIRCLE,
|
||||||
|
SHAPE_SPHERE,
|
||||||
|
SHAPE_CYLINDER,
|
||||||
|
SHAPE_CAPSULE,
|
||||||
|
SHAPE_TORUS,
|
||||||
|
SHAPE_MONKEY
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t hash;
|
||||||
|
gpu_buffer* vertices;
|
||||||
|
gpu_buffer* indices;
|
||||||
|
} Shape;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Sync* sync;
|
Sync* sync;
|
||||||
Buffer* buffer;
|
Buffer* buffer;
|
||||||
|
@ -277,6 +293,7 @@ struct Pass {
|
||||||
gpu_binding builtins[3];
|
gpu_binding builtins[3];
|
||||||
gpu_buffer* vertexBuffer;
|
gpu_buffer* vertexBuffer;
|
||||||
gpu_buffer* indexBuffer;
|
gpu_buffer* indexBuffer;
|
||||||
|
Shape shapeCache[16];
|
||||||
arr_t(Access) access;
|
arr_t(Access) access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2366,7 +2383,6 @@ Model* lovrModelCreate(ModelInfo* info) {
|
||||||
|
|
||||||
draw->material = primitive->material == ~0u ? NULL: model->materials[primitive->material];
|
draw->material = primitive->material == ~0u ? NULL: model->materials[primitive->material];
|
||||||
draw->vertex.buffer = model->vertexBuffer;
|
draw->vertex.buffer = model->vertexBuffer;
|
||||||
draw->index.stride = indexSize;
|
|
||||||
|
|
||||||
if (primitive->indices) {
|
if (primitive->indices) {
|
||||||
draw->index.buffer = model->indexBuffer;
|
draw->index.buffer = model->indexBuffer;
|
||||||
|
@ -2895,6 +2911,8 @@ Pass* lovrGraphicsGetPass(PassInfo* info) {
|
||||||
pass->vertexBuffer = NULL;
|
pass->vertexBuffer = NULL;
|
||||||
pass->indexBuffer = NULL;
|
pass->indexBuffer = NULL;
|
||||||
|
|
||||||
|
memset(pass->shapeCache, 0, sizeof(pass->shapeCache));
|
||||||
|
|
||||||
float viewport[6] = { 0.f, 0.f, (float) main->width, (float) main->height, 0.f, 1.f };
|
float viewport[6] = { 0.f, 0.f, (float) main->width, (float) main->height, 0.f, 1.f };
|
||||||
lovrPassSetViewport(pass, viewport, viewport + 4);
|
lovrPassSetViewport(pass, viewport, viewport + 4);
|
||||||
|
|
||||||
|
@ -3583,22 +3601,29 @@ static void flushMaterial(Pass* pass, Draw* draw, Shader* shader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void flushBuffers(Pass* pass, Draw* draw) {
|
static void flushBuffers(Pass* pass, Draw* draw) {
|
||||||
|
Shape* cache = NULL;
|
||||||
|
|
||||||
|
if (draw->hash) {
|
||||||
|
cache = &pass->shapeCache[draw->hash & (COUNTOF(pass->shapeCache) - 1)];
|
||||||
|
if (cache->hash == draw->hash) {
|
||||||
|
gpu_bind_vertex_buffers(pass->stream, &cache->vertices, NULL, 0, 1);
|
||||||
|
gpu_bind_index_buffer(pass->stream, cache->indices, 0, GPU_INDEX_U16);
|
||||||
|
*draw->vertex.pointer = NULL;
|
||||||
|
*draw->index.pointer = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!draw->vertex.buffer && draw->vertex.count > 0) {
|
if (!draw->vertex.buffer && draw->vertex.count > 0) {
|
||||||
lovrCheck(draw->vertex.count < UINT16_MAX, "This draw has too many vertices (max is 65534), try splitting it up into multiple draws or using a Buffer");
|
lovrCheck(draw->vertex.count < UINT16_MAX, "This draw has too many vertices (max is 65534), try splitting it up into multiple draws or using a Buffer");
|
||||||
uint32_t stride = state.vertexFormats[draw->vertex.format].bufferStrides[0];
|
uint32_t stride = state.vertexFormats[draw->vertex.format].bufferStrides[0];
|
||||||
uint32_t size = draw->vertex.count * stride;
|
uint32_t size = draw->vertex.count * stride;
|
||||||
|
|
||||||
gpu_buffer* scratchpad = tempAlloc(gpu_sizeof_buffer());
|
gpu_buffer* scratchpad = tempAlloc(gpu_sizeof_buffer());
|
||||||
void* pointer = gpu_map(scratchpad, size, stride, GPU_MAP_WRITE);
|
*draw->vertex.pointer = gpu_map(scratchpad, size, stride, GPU_MAP_WRITE);
|
||||||
|
|
||||||
if (draw->vertex.pointer) {
|
|
||||||
*draw->vertex.pointer = pointer;
|
|
||||||
} else {
|
|
||||||
memcpy(pointer, draw->vertex.data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu_bind_vertex_buffers(pass->stream, &scratchpad, NULL, 0, 1);
|
gpu_bind_vertex_buffers(pass->stream, &scratchpad, NULL, 0, 1);
|
||||||
pass->vertexBuffer = NULL;
|
pass->vertexBuffer = scratchpad;
|
||||||
} else if (draw->vertex.buffer && draw->vertex.buffer->gpu != pass->vertexBuffer) {
|
} else if (draw->vertex.buffer && draw->vertex.buffer->gpu != pass->vertexBuffer) {
|
||||||
lovrCheck(draw->vertex.buffer->info.stride <= state.limits.vertexBufferStride, "Vertex buffer stride exceeds vertexBufferStride limit");
|
lovrCheck(draw->vertex.buffer->info.stride <= state.limits.vertexBufferStride, "Vertex buffer stride exceeds vertexBufferStride limit");
|
||||||
gpu_bind_vertex_buffers(pass->stream, &draw->vertex.buffer->gpu, NULL, 0, 1);
|
gpu_bind_vertex_buffers(pass->stream, &draw->vertex.buffer->gpu, NULL, 0, 1);
|
||||||
|
@ -3607,27 +3632,25 @@ static void flushBuffers(Pass* pass, Draw* draw) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!draw->index.buffer && draw->index.count > 0) {
|
if (!draw->index.buffer && draw->index.count > 0) {
|
||||||
uint32_t stride = draw->index.stride ? draw->index.stride : sizeof(uint16_t);
|
uint32_t size = draw->index.count * sizeof(uint16_t);
|
||||||
uint32_t size = draw->index.count * stride;
|
|
||||||
|
|
||||||
gpu_buffer* scratchpad = tempAlloc(gpu_sizeof_buffer());
|
gpu_buffer* scratchpad = tempAlloc(gpu_sizeof_buffer());
|
||||||
void* pointer = gpu_map(scratchpad, size, stride, GPU_MAP_WRITE);
|
*draw->index.pointer = gpu_map(scratchpad, size, sizeof(uint16_t), GPU_MAP_WRITE);
|
||||||
|
|
||||||
if (draw->index.pointer) {
|
gpu_bind_index_buffer(pass->stream, scratchpad, 0, GPU_INDEX_U16);
|
||||||
*draw->index.pointer = pointer;
|
pass->indexBuffer = scratchpad;
|
||||||
} else {
|
|
||||||
memcpy(pointer, draw->index.data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
gpu_index_type type = stride == 4 ? GPU_INDEX_U32 : GPU_INDEX_U16;
|
|
||||||
gpu_bind_index_buffer(pass->stream, scratchpad, 0, type);
|
|
||||||
pass->indexBuffer = NULL;
|
|
||||||
} else if (draw->index.buffer && draw->index.buffer->gpu != pass->indexBuffer) {
|
} else if (draw->index.buffer && draw->index.buffer->gpu != pass->indexBuffer) {
|
||||||
gpu_index_type type = draw->index.buffer->info.stride == 4 ? GPU_INDEX_U32 : GPU_INDEX_U16;
|
gpu_index_type type = draw->index.buffer->info.stride == 4 ? GPU_INDEX_U32 : GPU_INDEX_U16;
|
||||||
gpu_bind_index_buffer(pass->stream, draw->index.buffer->gpu, 0, type);
|
gpu_bind_index_buffer(pass->stream, draw->index.buffer->gpu, 0, type);
|
||||||
pass->indexBuffer = draw->index.buffer->gpu;
|
pass->indexBuffer = draw->index.buffer->gpu;
|
||||||
trackBuffer(pass, draw->index.buffer, GPU_PHASE_INPUT_INDEX, GPU_CACHE_INDEX);
|
trackBuffer(pass, draw->index.buffer, GPU_PHASE_INPUT_INDEX, GPU_CACHE_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
cache->hash = draw->hash;
|
||||||
|
cache->vertices = pass->vertexBuffer;
|
||||||
|
cache->indices = pass->indexBuffer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lovrPassDraw(Pass* pass, Draw* draw) {
|
static void lovrPassDraw(Pass* pass, Draw* draw) {
|
||||||
|
@ -3683,6 +3706,7 @@ void lovrPassLine(Pass* pass, uint32_t count, float** points) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPassPlane(Pass* pass, float* transform, DrawStyle style, uint32_t cols, uint32_t rows) {
|
void lovrPassPlane(Pass* pass, float* transform, DrawStyle style, uint32_t cols, uint32_t rows) {
|
||||||
|
uint32_t key[] = { SHAPE_PLANE, style, cols, rows };
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
|
|
||||||
|
@ -3693,17 +3717,19 @@ void lovrPassPlane(Pass* pass, float* transform, DrawStyle style, uint32_t cols,
|
||||||
indexCount = 2 * (rows + 1) + 2 * (cols + 1);
|
indexCount = 2 * (rows + 1) + 2 * (cols + 1);
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_LINES,
|
.mode = VERTEX_LINES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
.vertex.count = vertexCount,
|
.vertex.count = vertexCount,
|
||||||
.index.pointer = (void**) &indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = indexCount
|
.index.count = indexCount,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
indexCount = (cols * rows) * 6;
|
indexCount = (cols * rows) * 6;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
@ -3713,6 +3739,10 @@ void lovrPassPlane(Pass* pass, float* transform, DrawStyle style, uint32_t cols,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (uint32_t y = 0; y <= rows; y++) {
|
for (uint32_t y = 0; y <= rows; y++) {
|
||||||
float v = y * (1.f / rows);
|
float v = y * (1.f / rows);
|
||||||
for (uint32_t x = 0; x <= cols; x++) {
|
for (uint32_t x = 0; x <= cols; x++) {
|
||||||
|
@ -3757,8 +3787,12 @@ void lovrPassPlane(Pass* pass, float* transform, DrawStyle style, uint32_t cols,
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPassBox(Pass* pass, float* transform, DrawStyle style) {
|
void lovrPassBox(Pass* pass, float* transform, DrawStyle style) {
|
||||||
|
uint32_t key[] = { SHAPE_BOX, style };
|
||||||
|
ShapeVertex* vertices;
|
||||||
|
uint16_t* indices;
|
||||||
|
|
||||||
if (style == STYLE_LINE) {
|
if (style == STYLE_LINE) {
|
||||||
static ShapeVertex vertices[] = {
|
static ShapeVertex vertexData[] = {
|
||||||
{ { -.5f, .5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } }, // Front
|
{ { -.5f, .5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } }, // Front
|
||||||
{ { .5f, .5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } },
|
{ { .5f, .5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } },
|
||||||
{ { .5f, -.5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } },
|
{ { .5f, -.5f, -.5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } },
|
||||||
|
@ -3769,22 +3803,28 @@ void lovrPassBox(Pass* pass, float* transform, DrawStyle style) {
|
||||||
{ { -.5f, -.5f, .5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } }
|
{ { -.5f, -.5f, .5f }, { 0.f, 0.f, 0.f }, { 0.f, 0.f } }
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint16_t indices[] = {
|
static uint16_t indexData[] = {
|
||||||
0, 1, 1, 2, 2, 3, 3, 0, // Front
|
0, 1, 1, 2, 2, 3, 3, 0, // Front
|
||||||
4, 5, 5, 6, 6, 7, 7, 4, // Back
|
4, 5, 5, 6, 6, 7, 7, 4, // Back
|
||||||
0, 4, 1, 5, 2, 6, 3, 7 // Connections
|
0, 4, 1, 5, 2, 6, 3, 7 // Connections
|
||||||
};
|
};
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_LINES,
|
.mode = VERTEX_LINES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.data = vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
.vertex.count = COUNTOF(vertices),
|
.vertex.count = COUNTOF(vertexData),
|
||||||
.index.data = indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = COUNTOF(indices)
|
.index.count = COUNTOF(indexData)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (vertices) {
|
||||||
|
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||||
|
memcpy(indices, indexData, sizeof(indexData));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ShapeVertex vertices[] = {
|
static ShapeVertex vertexData[] = {
|
||||||
{ { -.5f, -.5f, -.5f }, { 0.f, 0.f, -1.f }, { 0.f, 0.f } }, // Front
|
{ { -.5f, -.5f, -.5f }, { 0.f, 0.f, -1.f }, { 0.f, 0.f } }, // Front
|
||||||
{ { -.5f, .5f, -.5f }, { 0.f, 0.f, -1.f }, { 0.f, 1.f } },
|
{ { -.5f, .5f, -.5f }, { 0.f, 0.f, -1.f }, { 0.f, 1.f } },
|
||||||
{ { .5f, -.5f, -.5f }, { 0.f, 0.f, -1.f }, { 1.f, 0.f } },
|
{ { .5f, -.5f, -.5f }, { 0.f, 0.f, -1.f }, { 1.f, 0.f } },
|
||||||
|
@ -3811,7 +3851,7 @@ void lovrPassBox(Pass* pass, float* transform, DrawStyle style) {
|
||||||
{ { .5f, .5f, .5f }, { 0.f, 1.f, 0.f }, { 1.f, 0.f } }
|
{ { .5f, .5f, .5f }, { 0.f, 1.f, 0.f }, { 1.f, 0.f } }
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t indices[] = {
|
static uint16_t indexData[] = {
|
||||||
0, 1, 2, 2, 1, 3,
|
0, 1, 2, 2, 1, 3,
|
||||||
4, 5, 6, 6, 5, 7,
|
4, 5, 6, 6, 5, 7,
|
||||||
8, 9, 10, 10, 9, 11,
|
8, 9, 10, 10, 9, 11,
|
||||||
|
@ -3821,13 +3861,19 @@ void lovrPassBox(Pass* pass, float* transform, DrawStyle style) {
|
||||||
};
|
};
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.data = vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
.vertex.count = COUNTOF(vertices),
|
.vertex.count = COUNTOF(vertexData),
|
||||||
.index.data = indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = COUNTOF(indices)
|
.index.count = COUNTOF(indexData)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (vertices) {
|
||||||
|
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||||
|
memcpy(indices, indexData, sizeof(indexData));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3837,6 +3883,7 @@ void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1,
|
||||||
angle2 = 2.f * (float) M_PI;
|
angle2 = 2.f * (float) M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t key[] = { SHAPE_CIRCLE, style, FLOAT_BITS(angle1), FLOAT_BITS(angle2), segments };
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
|
|
||||||
|
@ -3845,6 +3892,7 @@ void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1,
|
||||||
uint32_t indexCount = segments * 2;
|
uint32_t indexCount = segments * 2;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_LINES,
|
.mode = VERTEX_LINES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
@ -3852,11 +3900,16 @@ void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1,
|
||||||
.index.pointer = (void**) &indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = indexCount
|
.index.count = indexCount
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uint32_t vertexCount = segments + 2;
|
uint32_t vertexCount = segments + 2;
|
||||||
uint32_t indexCount = segments * 3;
|
uint32_t indexCount = segments * 3;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
@ -3865,6 +3918,10 @@ void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1,
|
||||||
.index.count = indexCount
|
.index.count = indexCount
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Center
|
// Center
|
||||||
*vertices++ = (ShapeVertex) { { 0.f, 0.f, 0.f }, { 0.f, 0.f, 1.f }, { .5f, .5f } };
|
*vertices++ = (ShapeVertex) { { 0.f, 0.f, 0.f }, { 0.f, 0.f, 1.f }, { .5f, .5f } };
|
||||||
}
|
}
|
||||||
|
@ -3898,15 +3955,22 @@ void lovrPassSphere(Pass* pass, float* transform, uint32_t segmentsH, uint32_t s
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
|
|
||||||
|
uint32_t key[] = { SHAPE_SPHERE, segmentsH, segmentsV };
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
.vertex.count = vertexCount,
|
.vertex.count = vertexCount,
|
||||||
.index.pointer = (void**) &indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = indexCount
|
.index.count = indexCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Top
|
// Top
|
||||||
*vertices++ = (ShapeVertex) { { 0.f, 1.f, 0.f }, { 0.f, 1.f, 0.f }, { .5f, 0.f } };
|
*vertices++ = (ShapeVertex) { { 0.f, 1.f, 0.f }, { 0.f, 1.f, 0.f }, { .5f, 0.f } };
|
||||||
|
|
||||||
|
@ -3965,6 +4029,8 @@ void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, f
|
||||||
angle2 = 2.f * (float) M_PI;
|
angle2 = 2.f * (float) M_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t key[] = { SHAPE_CYLINDER, capped, FLOAT_BITS(angle1), FLOAT_BITS(angle2), segments };
|
||||||
|
|
||||||
uint32_t vertexCount = 2 * (segments + 1);
|
uint32_t vertexCount = 2 * (segments + 1);
|
||||||
uint32_t indexCount = 6 * segments;
|
uint32_t indexCount = 6 * segments;
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
|
@ -3977,6 +4043,7 @@ void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, f
|
||||||
}
|
}
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
@ -3985,6 +4052,10 @@ void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, f
|
||||||
.index.count = indexCount
|
.index.count = indexCount
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float angleShift = (angle2 - angle1) / segments;
|
float angleShift = (angle2 - angle1) / segments;
|
||||||
|
|
||||||
// Tube
|
// Tube
|
||||||
|
@ -4046,6 +4117,8 @@ void lovrPassCapsule(Pass* pass, float* transform, uint32_t segments) {
|
||||||
float radius = sx;
|
float radius = sx;
|
||||||
float length = sz * .5f;
|
float length = sz * .5f;
|
||||||
|
|
||||||
|
uint32_t key[] = { SHAPE_CAPSULE, FLOAT_BITS(radius), FLOAT_BITS(length), segments };
|
||||||
|
|
||||||
uint32_t rings = segments / 2;
|
uint32_t rings = segments / 2;
|
||||||
uint32_t vertexCount = 2 * (1 + rings * (segments + 1));
|
uint32_t vertexCount = 2 * (1 + rings * (segments + 1));
|
||||||
uint32_t indexCount = 2 * (3 * segments + 6 * segments * (rings - 1)) + 6 * segments;
|
uint32_t indexCount = 2 * (3 * segments + 6 * segments * (rings - 1)) + 6 * segments;
|
||||||
|
@ -4053,14 +4126,19 @@ void lovrPassCapsule(Pass* pass, float* transform, uint32_t segments) {
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
.vertex.count = vertexCount,
|
.vertex.count = vertexCount,
|
||||||
.index.pointer = (void**) &indices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = indexCount
|
.index.count = indexCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
float tip = length + radius;
|
float tip = length + radius;
|
||||||
uint32_t h = vertexCount / 2;
|
uint32_t h = vertexCount / 2;
|
||||||
vertices[0] = (ShapeVertex) { { 0.f, 0.f, -tip }, { 0.f, 0.f, -1.f }, { .5f, 0.f } };
|
vertices[0] = (ShapeVertex) { { 0.f, 0.f, -tip }, { 0.f, 0.f, -1.f }, { .5f, 0.f } };
|
||||||
|
@ -4133,12 +4211,14 @@ void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t se
|
||||||
float radius = sx * .5f;
|
float radius = sx * .5f;
|
||||||
float thickness = sz * .5f;
|
float thickness = sz * .5f;
|
||||||
|
|
||||||
|
uint32_t key[] = { SHAPE_TORUS, FLOAT_BITS(radius), FLOAT_BITS(thickness), segmentsT, segmentsP };
|
||||||
uint32_t vertexCount = segmentsT * segmentsP;
|
uint32_t vertexCount = segmentsT * segmentsP;
|
||||||
uint32_t indexCount = segmentsT * segmentsP * 6;
|
uint32_t indexCount = segmentsT * segmentsP * 6;
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
@ -4311,6 +4391,7 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
||||||
mat4_scale(transform, scale, scale, scale);
|
mat4_scale(transform, scale, scale, scale);
|
||||||
mat4_translate(transform, 0.f, -ascent + valign / 2.f * (leading * lineCount), 0.f);
|
mat4_translate(transform, 0.f, -ascent + valign / 2.f * (leading * lineCount), 0.f);
|
||||||
|
|
||||||
|
GlyphVertex* vertexPointer;
|
||||||
uint16_t* indices;
|
uint16_t* indices;
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
|
@ -4318,12 +4399,14 @@ void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count
|
||||||
.material = font->material,
|
.material = font->material,
|
||||||
.transform = transform,
|
.transform = transform,
|
||||||
.vertex.format = VERTEX_GLYPH,
|
.vertex.format = VERTEX_GLYPH,
|
||||||
|
.vertex.pointer = (void**) &vertexPointer,
|
||||||
.vertex.count = glyphCount * 4,
|
.vertex.count = glyphCount * 4,
|
||||||
.vertex.data = vertices,
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = glyphCount * 6,
|
.index.count = glyphCount * 6
|
||||||
.index.pointer = (void**) &indices
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
memcpy(vertexPointer, vertices, glyphCount * 4 * sizeof(GlyphVertex));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < glyphCount * 4; i += 4) {
|
for (uint32_t i = 0; i < glyphCount * 4; i += 4) {
|
||||||
uint16_t quad[] = { i + 0, i + 2, i + 1, i + 1, i + 2, i + 3 };
|
uint16_t quad[] = { i + 0, i + 2, i + 1, i + 1, i + 2, i + 3 };
|
||||||
memcpy(indices, quad, sizeof(quad));
|
memcpy(indices, quad, sizeof(quad));
|
||||||
|
@ -4364,18 +4447,25 @@ void lovrPassFill(Pass* pass, Texture* texture) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void lovrPassMonkey(Pass* pass, float* transform) {
|
void lovrPassMonkey(Pass* pass, float* transform) {
|
||||||
|
uint32_t key[] = { SHAPE_MONKEY };
|
||||||
uint32_t vertexCount = COUNTOF(monkey_vertices) / 6;
|
uint32_t vertexCount = COUNTOF(monkey_vertices) / 6;
|
||||||
|
|
||||||
ShapeVertex* vertices;
|
ShapeVertex* vertices;
|
||||||
|
uint16_t* indices;
|
||||||
|
|
||||||
lovrPassDraw(pass, &(Draw) {
|
lovrPassDraw(pass, &(Draw) {
|
||||||
|
.hash = hash64(key, sizeof(key)),
|
||||||
.mode = VERTEX_TRIANGLES,
|
.mode = VERTEX_TRIANGLES,
|
||||||
.vertex.count = vertexCount,
|
|
||||||
.vertex.pointer = (void**) &vertices,
|
.vertex.pointer = (void**) &vertices,
|
||||||
|
.vertex.count = vertexCount,
|
||||||
|
.index.pointer = (void**) &indices,
|
||||||
.index.count = COUNTOF(monkey_indices),
|
.index.count = COUNTOF(monkey_indices),
|
||||||
.index.data = monkey_indices,
|
|
||||||
.transform = transform
|
.transform = transform
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!vertices) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Manual vertex format conversion to avoid another format (and sn8x3 isn't always supported)
|
// Manual vertex format conversion to avoid another format (and sn8x3 isn't always supported)
|
||||||
for (uint32_t i = 0; i < vertexCount; i++) {
|
for (uint32_t i = 0; i < vertexCount; i++) {
|
||||||
vertices[i] = (ShapeVertex) {
|
vertices[i] = (ShapeVertex) {
|
||||||
|
@ -4387,6 +4477,8 @@ void lovrPassMonkey(Pass* pass, float* transform) {
|
||||||
.normal.z = monkey_vertices[6 * i + 5] / 255.f * 2.f - 1.f,
|
.normal.z = monkey_vertices[6 * i + 5] / 255.f * 2.f - 1.f,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(indices, monkey_indices, sizeof(monkey_indices));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void renderNode(Pass* pass, Model* model, uint32_t index, bool recurse, uint32_t instances) {
|
static void renderNode(Pass* pass, Model* model, uint32_t index, bool recurse, uint32_t instances) {
|
||||||
|
|
Loading…
Reference in New Issue