mirror of https://github.com/bjornbytes/lovr.git
Write vertices at batch time;
This commit is contained in:
parent
7409f34d36
commit
efbc88073e
|
@ -90,6 +90,7 @@ static int l_lovrMeshDraw(lua_State* L) {
|
|||
.rangeCount = rangeCount ? rangeCount : defaultCount,
|
||||
.instances = instances
|
||||
},
|
||||
.drawMode = lovrMeshGetDrawMode(mesh),
|
||||
.transform = transform,
|
||||
.material = lovrMeshGetMaterial(mesh)
|
||||
});
|
||||
|
|
|
@ -104,11 +104,6 @@ static void* lovrGraphicsMapBuffer(BufferRole role, uint32_t count) {
|
|||
// Locks are placed as late as possible, causing the last lock to never get placed. Whenever we
|
||||
// wrap around a buffer, we gotta place that last missing lock.
|
||||
state.locks[role][MAX_LOCKS - 1] = lovrGpuLock();
|
||||
|
||||
// If we roll over the vertex/index streams, we can't reuse their contents
|
||||
if (role == STREAM_VERTEX || role == STREAM_INDEX) {
|
||||
state.cachedGeometry.vertexCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait on any pending locks for the mapped region(s)
|
||||
|
@ -152,8 +147,6 @@ static bool areBatchParamsEqual(BatchType typeA, BatchType typeB, BatchParams* a
|
|||
}
|
||||
}
|
||||
|
||||
static void writeGeometry(Batch* batch, float* vertices, uint16_t* indices, uint16_t I, uint32_t vertexCount, int n);
|
||||
|
||||
// Base
|
||||
|
||||
bool lovrGraphicsInit(bool gammaCorrect) {
|
||||
|
@ -520,32 +513,14 @@ void lovrGraphicsBatch(BatchRequest* req) {
|
|||
}
|
||||
}
|
||||
|
||||
size_t streamRequirements[] = {
|
||||
[STREAM_VERTEX] = req->vertexCount,
|
||||
[STREAM_INDEX] = req->indexCount,
|
||||
[STREAM_DRAW_ID] = req->vertexCount,
|
||||
[STREAM_DRAW_DATA] = 0
|
||||
};
|
||||
if (!req->instanced || !batch) {
|
||||
*(req->vertices) = lovrGraphicsMapBuffer(STREAM_VERTEX, req->vertexCount);
|
||||
uint8_t* ids = lovrGraphicsMapBuffer(STREAM_DRAW_ID, req->vertexCount);
|
||||
memset(ids, batch ? batch->drawCount : 0, req->vertexCount * sizeof(uint8_t));
|
||||
|
||||
if (!batch) {
|
||||
streamRequirements[STREAM_DRAW_DATA] = state.maxDraws;
|
||||
if (state.batchCount >= MAX_BATCHES) {
|
||||
lovrGraphicsFlush();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_BUFFER_ROLES; i++) {
|
||||
if (streamRequirements[i] > 0 && state.cursors[i] + streamRequirements[i] > BUFFER_COUNTS[i]) {
|
||||
uint32_t oldCursor = state.cursors[i];
|
||||
lovrGraphicsFlush();
|
||||
state.locks[i][MAX_LOCKS - 1] = lovrGpuLock();
|
||||
state.cursors[i] = state.cursors[i] >= oldCursor ? 0 : state.cursors[i];
|
||||
batch = NULL;
|
||||
streamRequirements[STREAM_DRAW_DATA] = state.maxDraws;
|
||||
state.cachedGeometry.vertexCount = 0;
|
||||
i = 0;
|
||||
} else {
|
||||
streamRequirements[i] = 0;
|
||||
if (req->indexCount > 0) {
|
||||
*(req->indices) = lovrGraphicsMapBuffer(STREAM_INDEX, req->indexCount);
|
||||
*(req->baseVertex) = state.cursors[STREAM_VERTEX];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,17 +531,19 @@ void lovrGraphicsBatch(BatchRequest* req) {
|
|||
*batch = (Batch) {
|
||||
.type = req->type,
|
||||
.params = req->params,
|
||||
.drawMode = req->drawMode,
|
||||
.canvas = canvas,
|
||||
.shader = shader,
|
||||
.pipeline = *pipeline,
|
||||
.material = material,
|
||||
.vertexStart = req->vertexCount > 0 ? state.cursors[STREAM_VERTEX] : 0,
|
||||
.vertexStart = state.cursors[STREAM_VERTEX],
|
||||
.vertexCount = 0,
|
||||
.indexStart = req->indexCount > 0 ? state.cursors[STREAM_INDEX] : 0,
|
||||
.indexStart = state.cursors[STREAM_INDEX],
|
||||
.indexCount = 0,
|
||||
.drawStart = state.cursors[STREAM_DRAW_DATA],
|
||||
.drawCount = 0,
|
||||
.drawData = drawData
|
||||
.drawData = drawData,
|
||||
.instanced = req->instanced
|
||||
};
|
||||
|
||||
state.cursors[STREAM_DRAW_DATA] += state.maxDraws;
|
||||
|
@ -586,18 +563,7 @@ void lovrGraphicsBatch(BatchRequest* req) {
|
|||
gammaCorrectColor(&color);
|
||||
batch->drawData[batch->drawCount].color = color;
|
||||
|
||||
// Handle streams
|
||||
uint8_t* ids = NULL;
|
||||
if (req->vertexCount > 0) {
|
||||
*(req->vertices) = lovrGraphicsMapBuffer(STREAM_VERTEX, req->vertexCount);
|
||||
ids = lovrGraphicsMapBuffer(STREAM_DRAW_ID, req->vertexCount);
|
||||
memset(ids, batch->drawCount, req->vertexCount * sizeof(uint8_t));
|
||||
|
||||
if (req->indexCount > 0) {
|
||||
*(req->indices) = lovrGraphicsMapBuffer(STREAM_INDEX, req->indexCount);
|
||||
*(req->baseVertex) = state.cursors[STREAM_VERTEX];
|
||||
}
|
||||
|
||||
if (!req->instanced || batch->drawCount == 0) {
|
||||
batch->vertexCount += req->vertexCount;
|
||||
batch->indexCount += req->indexCount;
|
||||
|
||||
|
@ -621,145 +587,15 @@ void lovrGraphicsFlush() {
|
|||
for (int b = 0; b < batchCount; b++) {
|
||||
Batch* batch = &state.batches[b];
|
||||
BatchParams* params = &batch->params;
|
||||
|
||||
// Resolve geometry
|
||||
Mesh* mesh = NULL;
|
||||
DrawMode drawMode;
|
||||
bool instanced = batch->vertexCount == 0 && batch->drawCount >= 4;
|
||||
int instances = instanced ? batch->drawCount : 1;
|
||||
uint32_t vertexCount = 0;
|
||||
uint32_t indexCount = 0;
|
||||
switch (batch->type) {
|
||||
case BATCH_POINTS: mesh = state.mesh; drawMode = DRAW_POINTS; break;
|
||||
case BATCH_LINES: mesh = state.mesh; drawMode = DRAW_LINE_STRIP; break;
|
||||
case BATCH_TRIANGLES:
|
||||
mesh = state.mesh;
|
||||
drawMode = params->triangles.style == STYLE_LINE ? DRAW_LINE_LOOP : DRAW_TRIANGLES;
|
||||
break;
|
||||
|
||||
case BATCH_PLANE:
|
||||
vertexCount = 4;
|
||||
indexCount = params->plane.style == STYLE_LINE ? 5 : 6;
|
||||
mesh = instanced ? state.instancedMesh : state.mesh;
|
||||
drawMode = params->plane.style == STYLE_LINE ? DRAW_LINE_LOOP : DRAW_TRIANGLES;
|
||||
break;
|
||||
|
||||
case BATCH_BOX:
|
||||
vertexCount = params->box.style == STYLE_LINE ? 8 : 24;
|
||||
indexCount = params->box.style == STYLE_LINE ? 24 : 36;
|
||||
mesh = instanced ? state.instancedMesh : state.mesh;
|
||||
drawMode = params->box.style == STYLE_LINE ? DRAW_LINES : DRAW_TRIANGLES;
|
||||
break;
|
||||
|
||||
case BATCH_ARC: {
|
||||
bool hasCenterPoint = params->arc.mode == ARC_MODE_PIE && fabsf(params->arc.r1 - params->arc.r2) < 2.f * (float) M_PI;
|
||||
vertexCount = params->arc.segments + 1 + hasCenterPoint;
|
||||
indexCount = vertexCount + 1;
|
||||
mesh = instanced ? state.instancedMesh : state.mesh;
|
||||
drawMode = params->arc.style == STYLE_LINE ? (params->arc.mode == ARC_MODE_OPEN ? DRAW_LINE_STRIP : DRAW_LINE_LOOP) : DRAW_TRIANGLE_FAN;
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_CYLINDER: {
|
||||
bool r1 = params->cylinder.r1 > 0;
|
||||
bool r2 = params->cylinder.r2 > 0;
|
||||
bool capped = params->cylinder.capped;
|
||||
int segments = params->cylinder.segments;
|
||||
vertexCount = ((capped && r1) * (segments + 2) + (capped && r2) * (segments + 2) + 2 * (segments + 1));
|
||||
indexCount = 3 * segments * ((capped && r1) + (capped && r2) + 2);
|
||||
mesh = instanced ? state.instancedMesh : state.mesh;
|
||||
drawMode = DRAW_TRIANGLES;
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_SPHERE: {
|
||||
int segments = params->sphere.segments;
|
||||
vertexCount = (segments + 1) * (segments + 1);
|
||||
indexCount = segments * segments * 6;
|
||||
mesh = instanced ? state.instancedMesh : state.mesh;
|
||||
drawMode = DRAW_TRIANGLES;
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_SKYBOX:
|
||||
vertexCount = 4;
|
||||
instanced = false;
|
||||
instances = 1;
|
||||
mesh = state.mesh;
|
||||
drawMode = DRAW_TRIANGLE_STRIP;
|
||||
break;
|
||||
|
||||
case BATCH_TEXT:
|
||||
mesh = state.mesh;
|
||||
drawMode = DRAW_TRIANGLES;
|
||||
break;
|
||||
|
||||
case BATCH_FILL:
|
||||
vertexCount = 4;
|
||||
instanced = false;
|
||||
instances = 1;
|
||||
mesh = state.mesh;
|
||||
drawMode = DRAW_TRIANGLE_STRIP;
|
||||
break;
|
||||
|
||||
case BATCH_MESH:
|
||||
mesh = params->mesh.object;
|
||||
drawMode = lovrMeshGetDrawMode(mesh);
|
||||
if (params->mesh.instances > 1) {
|
||||
lovrMeshSetAttributeEnabled(mesh, "lovrDrawID", false);
|
||||
instances = params->mesh.instances;
|
||||
} else {
|
||||
lovrMeshSetAttributeEnabled(mesh, "lovrDrawID", true);
|
||||
instances = batch->drawCount;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Write geometry
|
||||
if (vertexCount > 0) {
|
||||
int n = instanced ? 1 : batch->drawCount;
|
||||
|
||||
// Try to re-use the geometry from the last batch
|
||||
Batch* cached = &state.cachedGeometry;
|
||||
if (areBatchParamsEqual(batch->type, cached->type, &batch->params, &cached->params) && cached->vertexCount >= vertexCount * n) {
|
||||
batch->vertexStart = cached->vertexStart;
|
||||
batch->indexStart = cached->indexStart;
|
||||
batch->vertexCount = vertexCount * n;
|
||||
batch->indexCount = indexCount * n;
|
||||
} else {
|
||||
float* vertices = lovrGraphicsMapBuffer(STREAM_VERTEX, vertexCount * n);
|
||||
uint16_t* indices = lovrGraphicsMapBuffer(STREAM_INDEX, indexCount * n);
|
||||
uint16_t I = (uint16_t) state.cursors[STREAM_VERTEX];
|
||||
|
||||
cached->type = batch->type;
|
||||
cached->params = batch->params;
|
||||
batch->vertexStart = cached->vertexStart = state.cursors[STREAM_VERTEX];
|
||||
batch->indexStart = cached->indexStart = state.cursors[STREAM_INDEX];
|
||||
batch->vertexCount = cached->vertexCount = vertexCount * n;
|
||||
batch->indexCount = cached->indexCount = indexCount * n;
|
||||
|
||||
uint8_t* ids = lovrGraphicsMapBuffer(STREAM_DRAW_ID, batch->vertexCount);
|
||||
for (int i = 0; i < n; i++) {
|
||||
memset(ids, i, vertexCount * sizeof(uint8_t));
|
||||
ids += vertexCount;
|
||||
}
|
||||
|
||||
state.cursors[STREAM_VERTEX] += batch->vertexCount;
|
||||
state.cursors[STREAM_INDEX] += batch->indexCount;
|
||||
state.cursors[STREAM_DRAW_ID] += batch->vertexCount;
|
||||
|
||||
writeGeometry(batch, vertices, indices, I, vertexCount, n);
|
||||
}
|
||||
}
|
||||
Mesh* mesh = batch->type == BATCH_MESH ? params->mesh.object : (batch->instanced ? state.instancedMesh : state.mesh);
|
||||
int instances = batch->instanced ? batch->drawCount : 1;
|
||||
|
||||
// Flush vertex buffer
|
||||
if (batch->vertexCount > 0) {
|
||||
size_t stride = BUFFER_STRIDES[STREAM_VERTEX];
|
||||
lovrBufferFlushRange(state.buffers[STREAM_VERTEX], batch->vertexStart * stride, batch->vertexCount * stride);
|
||||
|
||||
if (!instanced) {
|
||||
if (!batch->instanced) {
|
||||
lovrBufferFlushRange(state.buffers[STREAM_DRAW_ID], batch->vertexStart, batch->vertexCount);
|
||||
}
|
||||
}
|
||||
|
@ -781,14 +617,21 @@ void lovrGraphicsFlush() {
|
|||
lovrShaderSetMatrices(batch->shader, "lovrViews", state.camera.viewMatrix[0], 0, 32);
|
||||
lovrShaderSetMatrices(batch->shader, "lovrProjections", state.camera.projection[0], 0, 32);
|
||||
|
||||
if (drawMode == DRAW_POINTS) {
|
||||
if (batch->drawMode == DRAW_POINTS) {
|
||||
lovrShaderSetFloats(batch->shader, "lovrPointSize", &state.pointSize, 0, 1);
|
||||
}
|
||||
|
||||
uint32_t rangeStart, rangeCount;
|
||||
if (batch->type == BATCH_MESH) {
|
||||
rangeStart = batch->params.mesh.rangeStart;
|
||||
rangeCount = batch->params.mesh.rangeCount;
|
||||
rangeStart = params->mesh.rangeStart;
|
||||
rangeCount = params->mesh.rangeCount;
|
||||
if (params->mesh.instances > 1) {
|
||||
lovrMeshSetAttributeEnabled(mesh, "lovrDrawID", false);
|
||||
instances = params->mesh.instances;
|
||||
} else {
|
||||
lovrMeshSetAttributeEnabled(mesh, "lovrDrawID", true);
|
||||
instances = batch->drawCount;
|
||||
}
|
||||
} else {
|
||||
rangeStart = batch->indexCount ? batch->indexStart : batch->vertexStart;
|
||||
rangeCount = batch->indexCount ? batch->indexCount : batch->vertexCount;
|
||||
|
@ -805,7 +648,7 @@ void lovrGraphicsFlush() {
|
|||
.shader = batch->shader,
|
||||
.canvas = batch->canvas,
|
||||
.pipeline = batch->pipeline,
|
||||
.drawMode = drawMode,
|
||||
.drawMode = batch->drawMode,
|
||||
.instances = instances,
|
||||
.rangeStart = rangeStart,
|
||||
.rangeCount = rangeCount,
|
||||
|
@ -822,7 +665,7 @@ void lovrGraphicsFlush() {
|
|||
size_t lastLock = (batch->vertexStart + batch->vertexCount) / lockSize;
|
||||
for (size_t i = firstLock; i < lastLock; i++) {
|
||||
state.locks[STREAM_VERTEX][i] = lovrGpuLock();
|
||||
if (!instanced) {
|
||||
if (!batch->instanced) {
|
||||
state.locks[STREAM_DRAW_ID][i] = lovrGpuLock();
|
||||
}
|
||||
}
|
||||
|
@ -887,6 +730,7 @@ void lovrGraphicsFlushMesh(Mesh* mesh) {
|
|||
void lovrGraphicsPoints(uint32_t count, float** vertices) {
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_POINTS,
|
||||
.drawMode = DRAW_POINTS,
|
||||
.vertexCount = count,
|
||||
.vertices = vertices
|
||||
});
|
||||
|
@ -899,6 +743,7 @@ void lovrGraphicsLine(uint32_t count, float** vertices) {
|
|||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_LINES,
|
||||
.drawMode = DRAW_LINE_STRIP,
|
||||
.vertexCount = count,
|
||||
.vertices = vertices,
|
||||
.indexCount = indexCount,
|
||||
|
@ -920,6 +765,7 @@ void lovrGraphicsTriangle(DrawStyle style, Material* material, uint32_t count, f
|
|||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_TRIANGLES,
|
||||
.params.triangles.style = style,
|
||||
.drawMode = style == STYLE_LINE ? DRAW_LINE_LOOP : DRAW_TRIANGLES,
|
||||
.material = material,
|
||||
.vertexCount = count,
|
||||
.vertices = vertices,
|
||||
|
@ -939,29 +785,161 @@ void lovrGraphicsTriangle(DrawStyle style, Material* material, uint32_t count, f
|
|||
}
|
||||
|
||||
void lovrGraphicsPlane(DrawStyle style, Material* material, mat4 transform) {
|
||||
float* vertices = NULL;
|
||||
uint16_t* indices = NULL;
|
||||
uint16_t baseVertex;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_PLANE,
|
||||
.params.plane.style = style,
|
||||
.drawMode = style == STYLE_LINE ? DRAW_LINE_LOOP : DRAW_TRIANGLES,
|
||||
.material = material,
|
||||
.transform = transform
|
||||
.transform = transform,
|
||||
.vertexCount = 4,
|
||||
.indexCount = style == STYLE_LINE ? 5 : 6,
|
||||
.vertices = &vertices,
|
||||
.indices = &indices,
|
||||
.baseVertex = &baseVertex,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
if (style == STYLE_LINE) {
|
||||
static float vertexData[] = {
|
||||
-.5, .5, 0, 0, 0, 0, 0, 0,
|
||||
.5, .5, 0, 0, 0, 0, 0, 0,
|
||||
.5, -.5, 0, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||
|
||||
indices[0] = 0xffff;
|
||||
indices[1] = 0 + baseVertex;
|
||||
indices[2] = 1 + baseVertex;
|
||||
indices[3] = 2 + baseVertex;
|
||||
indices[4] = 3 + baseVertex;
|
||||
} else {
|
||||
static float vertexData[] = {
|
||||
-.5, .5, 0, 0, 0, -1, 0, 1,
|
||||
-.5, -.5, 0, 0, 0, -1, 0, 0,
|
||||
.5, .5, 0, 0, 0, -1, 1, 1,
|
||||
.5, -.5, 0, 0, 0, -1, 1, 0
|
||||
};
|
||||
|
||||
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||
|
||||
static uint16_t indexData[] = { 0, 1, 2, 2, 1, 3 };
|
||||
|
||||
for (size_t i = 0; i < sizeof(indexData) / sizeof(indexData[0]); i++) {
|
||||
indices[i] = indexData[i] + baseVertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsBox(DrawStyle style, Material* material, mat4 transform) {
|
||||
float* vertices = NULL;
|
||||
uint16_t* indices = NULL;
|
||||
uint16_t baseVertex;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_BOX,
|
||||
.params.box.style = style,
|
||||
.drawMode = style == STYLE_LINE ? DRAW_LINES : DRAW_TRIANGLES,
|
||||
.material = material,
|
||||
.transform = transform
|
||||
.transform = transform,
|
||||
.vertexCount = style == STYLE_LINE ? 8 : 24,
|
||||
.indexCount = style == STYLE_LINE ? 24 : 36,
|
||||
.vertices = &vertices,
|
||||
.indices = &indices,
|
||||
.baseVertex = &baseVertex,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
if (style == STYLE_LINE) {
|
||||
static float vertexData[] = {
|
||||
-.5, .5, -.5, 0, 0, 0, 0, 0, // Front
|
||||
.5, .5, -.5, 0, 0, 0, 0, 0,
|
||||
.5, -.5, -.5, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, -.5, 0, 0, 0, 0, 0,
|
||||
-.5, .5, .5, 0, 0, 0, 0, 0, // Back
|
||||
.5, .5, .5, 0, 0, 0, 0, 0,
|
||||
.5, -.5, .5, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, .5, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||
|
||||
static uint16_t indexData[] = {
|
||||
0, 1, 1, 2, 2, 3, 3, 0, // Front
|
||||
4, 5, 5, 6, 6, 7, 7, 4, // Back
|
||||
0, 4, 1, 5, 2, 6, 3, 7 // Connections
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(indexData) / sizeof(indexData[0]); i++) {
|
||||
indices[i] = indexData[i] + baseVertex;
|
||||
}
|
||||
} else {
|
||||
static float vertexData[] = {
|
||||
-.5, -.5, -.5, 0, 0, -1, 0, 0, // Front
|
||||
-.5, .5, -.5, 0, 0, -1, 0, 1,
|
||||
.5, -.5, -.5, 0, 0, -1, 1, 0,
|
||||
.5, .5, -.5, 0, 0, -1, 1, 1,
|
||||
.5, .5, -.5, 1, 0, 0, 0, 1, // Right
|
||||
.5, .5, .5, 1, 0, 0, 1, 1,
|
||||
.5, -.5, -.5, 1, 0, 0, 0, 0,
|
||||
.5, -.5, .5, 1, 0, 0, 1, 0,
|
||||
.5, -.5, .5, 0, 0, 1, 0, 0, // Back
|
||||
.5, .5, .5, 0, 0, 1, 0, 1,
|
||||
-.5, -.5, .5, 0, 0, 1, 1, 0,
|
||||
-.5, .5, .5, 0, 0, 1, 1, 1,
|
||||
-.5, .5, .5, -1, 0, 0, 0, 1, // Left
|
||||
-.5, .5, -.5, -1, 0, 0, 1, 1,
|
||||
-.5, -.5, .5, -1, 0, 0, 0, 0,
|
||||
-.5, -.5, -.5, -1, 0, 0, 1, 0,
|
||||
-.5, -.5, -.5, 0, -1, 0, 0, 0, // Bottom
|
||||
.5, -.5, -.5, 0, -1, 0, 1, 0,
|
||||
-.5, -.5, .5, 0, -1, 0, 0, 1,
|
||||
.5, -.5, .5, 0, -1, 0, 1, 1,
|
||||
-.5, .5, -.5, 0, 1, 0, 0, 1, // Top
|
||||
-.5, .5, .5, 0, 1, 0, 0, 0,
|
||||
.5, .5, -.5, 0, 1, 0, 1, 1,
|
||||
.5, .5, .5, 0, 1, 0, 1, 0
|
||||
};
|
||||
|
||||
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||
|
||||
uint16_t indexData[] = {
|
||||
0, 1, 2, 2, 1, 3,
|
||||
4, 5, 6, 6, 5, 7,
|
||||
8, 9, 10, 10, 9, 11,
|
||||
12, 13, 14, 14, 13, 15,
|
||||
16, 17, 18, 18, 17, 19,
|
||||
20, 21, 22, 22, 21, 23
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(indexData) / sizeof(indexData[0]); i++) {
|
||||
indices[i] = indexData[i] + baseVertex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsArc(DrawStyle style, ArcMode mode, Material* material, mat4 transform, float r1, float r2, int segments) {
|
||||
bool hasCenterPoint = false;
|
||||
|
||||
if (fabsf(r1 - r2) >= 2.f * (float) M_PI) {
|
||||
r1 = 0.f;
|
||||
r2 = 2.f * (float) M_PI;
|
||||
} else {
|
||||
hasCenterPoint = mode == ARC_MODE_PIE;
|
||||
}
|
||||
|
||||
uint32_t vertexCount = segments + 1 + hasCenterPoint;
|
||||
float* vertices = NULL;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_ARC,
|
||||
.params.arc.r1 = r1,
|
||||
|
@ -969,9 +947,31 @@ void lovrGraphicsArc(DrawStyle style, ArcMode mode, Material* material, mat4 tra
|
|||
.params.arc.mode = mode,
|
||||
.params.arc.style = style,
|
||||
.params.arc.segments = segments,
|
||||
.drawMode = style == STYLE_LINE ? (mode == ARC_MODE_OPEN ? DRAW_LINE_STRIP : DRAW_LINE_LOOP) : DRAW_TRIANGLE_FAN,
|
||||
.material = material,
|
||||
.transform = transform
|
||||
.transform = transform,
|
||||
.vertexCount = vertexCount,
|
||||
.vertices = &vertices,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
if (hasCenterPoint) {
|
||||
memcpy(vertices, ((float[]) { 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, .5f, .5f }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
|
||||
float theta = r1;
|
||||
float angleShift = (r2 - r1) / (float) segments;
|
||||
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float x = cosf(theta) * .5f;
|
||||
float y = sinf(theta) * .5f;
|
||||
memcpy(vertices, ((float[]) { x, y, 0.f, 0.f, 0.f, 1.f, x + .5f, 1.f - (y + .5f) }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
theta += angleShift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsCircle(DrawStyle style, Material* material, mat4 transform, int segments) {
|
||||
|
@ -980,25 +980,135 @@ void lovrGraphicsCircle(DrawStyle style, Material* material, mat4 transform, int
|
|||
|
||||
void lovrGraphicsCylinder(Material* material, mat4 transform, float r1, float r2, bool capped, int segments) {
|
||||
float length = vec3_length((float[3]) { transform[8], transform[9], transform[10] });
|
||||
r1 /= length;
|
||||
r2 /= length;
|
||||
|
||||
uint32_t vertexCount = ((capped && r1) * (segments + 2) + (capped && r2) * (segments + 2) + 2 * (segments + 1));
|
||||
uint32_t indexCount = 3 * segments * ((capped && r1) + (capped && r2) + 2);
|
||||
float* vertices = NULL;
|
||||
uint16_t* indices = NULL;
|
||||
uint16_t baseVertex;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_CYLINDER,
|
||||
.params.cylinder.r1 = r1 / length,
|
||||
.params.cylinder.r2 = r2 / length,
|
||||
.params.cylinder.r1 = r1,
|
||||
.params.cylinder.r2 = r2,
|
||||
.params.cylinder.capped = capped,
|
||||
.params.cylinder.segments = segments,
|
||||
.drawMode = DRAW_TRIANGLES,
|
||||
.material = material,
|
||||
.transform = transform
|
||||
.transform = transform,
|
||||
.vertexCount = vertexCount,
|
||||
.indexCount = indexCount,
|
||||
.vertices = &vertices,
|
||||
.indices = &indices,
|
||||
.baseVertex = &baseVertex,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
float* v = vertices;
|
||||
|
||||
// Ring
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float theta = i * (2 * M_PI) / segments;
|
||||
float X = cosf(theta);
|
||||
float Y = sinf(theta);
|
||||
memcpy(vertices, (float[16]) {
|
||||
r1 * X, r1 * Y, -.5f, X, Y, 0.f, 0.f, 0.f,
|
||||
r2 * X, r2 * Y, .5f, X, Y, 0.f, 0.f, 0.f
|
||||
}, 16 * sizeof(float));
|
||||
vertices += 16;
|
||||
}
|
||||
|
||||
// Top
|
||||
int top = (segments + 1) * 2 + baseVertex;
|
||||
if (capped && r1 != 0) {
|
||||
memcpy(vertices, (float[8]) { 0.f, 0.f, -.5f, 0.f, 0.f, -1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
int j = i * 2 * 8;
|
||||
memcpy(vertices, (float[8]) { v[j + 0], v[j + 1], v[j + 2], 0.f, 0.f, -1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom
|
||||
int bot = (segments + 1) * 2 + (1 + segments + 1) * (capped && r1 != 0) + baseVertex;
|
||||
if (capped && r2 != 0) {
|
||||
memcpy(vertices, (float[8]) { 0.f, 0.f, .5f, 0.f, 0.f, 1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
int j = i * 2 * 8 + 8;
|
||||
memcpy(vertices, (float[8]) { v[j + 0], v[j + 1], v[j + 2], 0.f, 0.f, 1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Indices
|
||||
for (int i = 0; i < segments; i++) {
|
||||
int j = 2 * i + baseVertex;
|
||||
memcpy(indices, (uint16_t[6]) { j, j + 1, j + 2, j + 1, j + 3, j + 2 }, 6 * sizeof(uint16_t));
|
||||
indices += 6;
|
||||
|
||||
if (capped && r1 != 0.f) {
|
||||
memcpy(indices, (uint16_t[3]) { top, top + i + 1, top + i + 2 }, 3 * sizeof(uint16_t));
|
||||
indices += 3;
|
||||
}
|
||||
|
||||
if (capped && r2 != 0.f) {
|
||||
memcpy(indices, (uint16_t[3]) { bot, bot + i + 1, bot + i + 2 }, 3 * sizeof(uint16_t));
|
||||
indices += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
|
||||
float* vertices = NULL;
|
||||
uint16_t* indices = NULL;
|
||||
uint16_t baseVertex;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_SPHERE,
|
||||
.params.sphere.segments = segments,
|
||||
.drawMode = DRAW_TRIANGLES,
|
||||
.material = material,
|
||||
.transform = transform
|
||||
.transform = transform,
|
||||
.vertexCount = (segments + 1) * (segments + 1),
|
||||
.indexCount = segments * segments * 6,
|
||||
.vertices = &vertices,
|
||||
.indices = &indices,
|
||||
.baseVertex = &baseVertex,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float v = i / (float) segments;
|
||||
float sinV = sinf(v * (float) M_PI);
|
||||
float cosV = cosf(v * (float) M_PI);
|
||||
for (int k = 0; k <= segments; k++) {
|
||||
float u = k / (float) segments;
|
||||
float x = sinf(u * 2.f * (float) M_PI) * sinV;
|
||||
float y = cosV;
|
||||
float z = -cosf(u * 2.f * (float) M_PI) * sinV;
|
||||
memcpy(vertices, ((float[8]) { x, y, z, x, y, z, u, 1.f - v }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < segments; i++) {
|
||||
uint16_t offset0 = i * (segments + 1) + baseVertex;
|
||||
uint16_t offset1 = (i + 1) * (segments + 1) + baseVertex;
|
||||
for (int j = 0; j < segments; j++) {
|
||||
uint16_t i0 = offset0 + j;
|
||||
uint16_t i1 = offset1 + j;
|
||||
memcpy(indices, ((uint16_t[]) { i0, i1, i0 + 1, i1, i1 + 1, i0 + 1 }), 6 * sizeof(uint16_t));
|
||||
indices += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az) {
|
||||
|
@ -1011,14 +1121,31 @@ void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float
|
|||
float transform[16] = MAT4_IDENTITY;
|
||||
mat4_rotate(transform, angle, ax, ay, az);
|
||||
|
||||
float* vertices = NULL;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_SKYBOX,
|
||||
.drawMode = DRAW_TRIANGLE_STRIP,
|
||||
.shader = type == TEXTURE_CUBE ? SHADER_CUBE : SHADER_PANO,
|
||||
.pipeline = &pipeline,
|
||||
.transform = transform,
|
||||
.diffuseTexture = type == TEXTURE_2D ? texture : NULL,
|
||||
.environmentMap = type == TEXTURE_CUBE ? texture : NULL
|
||||
.environmentMap = type == TEXTURE_CUBE ? texture : NULL,
|
||||
.vertexCount = 4,
|
||||
.vertices = &vertices,
|
||||
.instanced = true
|
||||
});
|
||||
|
||||
if (vertices) {
|
||||
static float vertexData[] = {
|
||||
-1, 1, 1, 0, 0, 0, 0, 0,
|
||||
-1, -1, 1, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0,
|
||||
1, -1, 1, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
memcpy(vertices, vertexData, sizeof(vertexData));
|
||||
}
|
||||
}
|
||||
|
||||
void lovrGraphicsPrint(const char* str, size_t length, mat4 transform, float wrap, HorizontalAlign halign, VerticalAlign valign) {
|
||||
|
@ -1041,6 +1168,7 @@ void lovrGraphicsPrint(const char* str, size_t length, mat4 transform, float wra
|
|||
uint16_t baseVertex;
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_TEXT,
|
||||
.drawMode = DRAW_TRIANGLES,
|
||||
.shader = SHADER_FONT,
|
||||
.pipeline = &pipeline,
|
||||
.transform = transform,
|
||||
|
@ -1060,277 +1188,25 @@ void lovrGraphicsFill(Texture* texture, float u, float v, float w, float h) {
|
|||
pipeline.depthTest = COMPARE_NONE;
|
||||
pipeline.depthWrite = false;
|
||||
|
||||
float* vertices = NULL;
|
||||
|
||||
lovrGraphicsBatch(&(BatchRequest) {
|
||||
.type = BATCH_FILL,
|
||||
.params.fill = { .u = u, .v = v, .w = w, .h = h },
|
||||
.drawMode = DRAW_TRIANGLE_STRIP,
|
||||
.shader = SHADER_FILL,
|
||||
.pipeline = &pipeline,
|
||||
.diffuseTexture = texture
|
||||
.diffuseTexture = texture,
|
||||
.vertexCount = 4,
|
||||
.vertices = &vertices
|
||||
});
|
||||
}
|
||||
|
||||
static void writeGeometry(Batch* batch, float* vertices, uint16_t* indices, uint16_t I, uint32_t vertexCount, int n) {
|
||||
BatchParams* params = &batch->params;
|
||||
switch (batch->type) {
|
||||
case BATCH_PLANE:
|
||||
if (params->plane.style == STYLE_LINE) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
memcpy(vertices, (float[32]) {
|
||||
-.5, .5, 0, 0, 0, 0, 0, 0,
|
||||
.5, .5, 0, 0, 0, 0, 0, 0,
|
||||
.5, -.5, 0, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, 0, 0, 0, 0, 0, 0
|
||||
}, 32 * sizeof(float));
|
||||
vertices += 32;
|
||||
|
||||
memcpy(indices, (uint16_t[5]) { 0xffff, I + 0, I + 1, I + 2, I + 3 }, 5 * sizeof(uint16_t));
|
||||
I += vertexCount;
|
||||
indices += 5;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
memcpy(vertices, (float[32]) {
|
||||
-.5, .5, 0, 0, 0, -1, 0, 1,
|
||||
-.5, -.5, 0, 0, 0, -1, 0, 0,
|
||||
.5, .5, 0, 0, 0, -1, 1, 1,
|
||||
.5, -.5, 0, 0, 0, -1, 1, 0
|
||||
}, 32 * sizeof(float));
|
||||
vertices += 32;
|
||||
|
||||
memcpy(indices, (uint16_t[6]) { I + 0, I + 1, I + 2, I + 2, I + 1, I + 3 }, 6 * sizeof(uint16_t));
|
||||
I += vertexCount;
|
||||
indices += 6;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BATCH_BOX:
|
||||
if (params->box.style == STYLE_LINE) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
memcpy(vertices, (float[64]) {
|
||||
-.5, .5, -.5, 0, 0, 0, 0, 0, // Front
|
||||
.5, .5, -.5, 0, 0, 0, 0, 0,
|
||||
.5, -.5, -.5, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, -.5, 0, 0, 0, 0, 0,
|
||||
-.5, .5, .5, 0, 0, 0, 0, 0, // Back
|
||||
.5, .5, .5, 0, 0, 0, 0, 0,
|
||||
.5, -.5, .5, 0, 0, 0, 0, 0,
|
||||
-.5, -.5, .5, 0, 0, 0, 0, 0
|
||||
}, 64 * sizeof(float));
|
||||
vertices += 64;
|
||||
|
||||
memcpy(indices, (uint16_t[24]) {
|
||||
I + 0, I + 1, I + 1, I + 2, I + 2, I + 3, I + 3, I + 0, // Front
|
||||
I + 4, I + 5, I + 5, I + 6, I + 6, I + 7, I + 7, I + 4, // Back
|
||||
I + 0, I + 4, I + 1, I + 5, I + 2, I + 6, I + 3, I + 7 // Connections
|
||||
}, 24 * sizeof(uint16_t));
|
||||
indices += 24;
|
||||
I += 8;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
memcpy(vertices, (float[192]) {
|
||||
-.5, -.5, -.5, 0, 0, -1, 0, 0, // Front
|
||||
-.5, .5, -.5, 0, 0, -1, 0, 1,
|
||||
.5, -.5, -.5, 0, 0, -1, 1, 0,
|
||||
.5, .5, -.5, 0, 0, -1, 1, 1,
|
||||
.5, .5, -.5, 1, 0, 0, 0, 1, // Right
|
||||
.5, .5, .5, 1, 0, 0, 1, 1,
|
||||
.5, -.5, -.5, 1, 0, 0, 0, 0,
|
||||
.5, -.5, .5, 1, 0, 0, 1, 0,
|
||||
.5, -.5, .5, 0, 0, 1, 0, 0, // Back
|
||||
.5, .5, .5, 0, 0, 1, 0, 1,
|
||||
-.5, -.5, .5, 0, 0, 1, 1, 0,
|
||||
-.5, .5, .5, 0, 0, 1, 1, 1,
|
||||
-.5, .5, .5, -1, 0, 0, 0, 1, // Left
|
||||
-.5, .5, -.5, -1, 0, 0, 1, 1,
|
||||
-.5, -.5, .5, -1, 0, 0, 0, 0,
|
||||
-.5, -.5, -.5, -1, 0, 0, 1, 0,
|
||||
-.5, -.5, -.5, 0, -1, 0, 0, 0, // Bottom
|
||||
.5, -.5, -.5, 0, -1, 0, 1, 0,
|
||||
-.5, -.5, .5, 0, -1, 0, 0, 1,
|
||||
.5, -.5, .5, 0, -1, 0, 1, 1,
|
||||
-.5, .5, -.5, 0, 1, 0, 0, 1, // Top
|
||||
-.5, .5, .5, 0, 1, 0, 0, 0,
|
||||
.5, .5, -.5, 0, 1, 0, 1, 1,
|
||||
.5, .5, .5, 0, 1, 0, 1, 0
|
||||
}, 192 * sizeof(float));
|
||||
vertices += 192;
|
||||
|
||||
memcpy(indices, (uint16_t[36]) {
|
||||
I + 0, I + 1, I + 2, I + 2, I + 1, I + 3,
|
||||
I + 4, I + 5, I + 6, I + 6, I + 5, I + 7,
|
||||
I + 8, I + 9, I + 10, I + 10, I + 9, I + 11,
|
||||
I + 12, I + 13, I + 14, I + 14, I + 13, I + 15,
|
||||
I + 16, I + 17, I + 18, I + 18, I + 17, I + 19,
|
||||
I + 20, I + 21, I + 22, I + 22, I + 21, I + 23
|
||||
}, 36 * sizeof(uint16_t));
|
||||
I += vertexCount;
|
||||
indices += 36;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BATCH_ARC: {
|
||||
float r1 = params->arc.r1;
|
||||
float r2 = params->arc.r2;
|
||||
int segments = params->arc.segments;
|
||||
bool hasCenterPoint = params->arc.mode == ARC_MODE_PIE && fabsf(r1 - r2) < 2.f * (float) M_PI;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (hasCenterPoint) {
|
||||
memcpy(vertices, ((float[]) { 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, .5f, .5f }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
|
||||
float theta = r1;
|
||||
float angleShift = (r2 - r1) / (float) segments;
|
||||
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float x = cosf(theta) * .5f;
|
||||
float y = sinf(theta) * .5f;
|
||||
memcpy(vertices, ((float[]) { x, y, 0.f, 0.f, 0.f, 1.f, x + .5f, 1.f - (y + .5f) }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
theta += angleShift;
|
||||
}
|
||||
|
||||
*indices++ = 0xffff;
|
||||
for (uint32_t i = 0; i < vertexCount; i++) {
|
||||
*indices++ = I + i;
|
||||
}
|
||||
I += vertexCount;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_CYLINDER: {
|
||||
bool capped = params->cylinder.capped;
|
||||
float r1 = params->cylinder.r1;
|
||||
float r2 = params->cylinder.r2;
|
||||
int segments = params->cylinder.segments;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
float* v = vertices;
|
||||
|
||||
// Ring
|
||||
for (int j = 0; j <= segments; j++) {
|
||||
float theta = j * (2 * M_PI) / segments;
|
||||
float X = cosf(theta);
|
||||
float Y = sinf(theta);
|
||||
memcpy(vertices, (float[16]) {
|
||||
r1 * X, r1 * Y, -.5f, X, Y, 0.f, 0.f, 0.f,
|
||||
r2 * X, r2 * Y, .5f, X, Y, 0.f, 0.f, 0.f
|
||||
}, 16 * sizeof(float));
|
||||
vertices += 16;
|
||||
}
|
||||
|
||||
// Top
|
||||
int top = (segments + 1) * 2 + I;
|
||||
if (capped && r1 != 0) {
|
||||
memcpy(vertices, (float[8]) { 0.f, 0.f, -.5f, 0.f, 0.f, -1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
for (int j = 0; j <= segments; j++) {
|
||||
int k = j * 2 * 8;
|
||||
memcpy(vertices, (float[8]) { v[k + 0], v[k + 1], v[k + 2], 0.f, 0.f, -1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom
|
||||
int bot = (segments + 1) * 2 + (1 + segments + 1) * (capped && r1 != 0) + I;
|
||||
if (capped && r2 != 0) {
|
||||
memcpy(vertices, (float[8]) { 0.f, 0.f, .5f, 0.f, 0.f, 1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
for (int j = 0; j <= segments; j++) {
|
||||
int k = j * 2 * 8 + 8;
|
||||
memcpy(vertices, (float[8]) { v[k + 0], v[k + 1], v[k + 2], 0.f, 0.f, 1.f, 0.f, 0.f }, 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Indices
|
||||
for (int i = 0; i < segments; i++) {
|
||||
int j = 2 * i + I;
|
||||
memcpy(indices, (uint16_t[6]) { j, j + 1, j + 2, j + 1, j + 3, j + 2 }, 6 * sizeof(uint16_t));
|
||||
indices += 6;
|
||||
|
||||
if (capped && r1 != 0.f) {
|
||||
memcpy(indices, (uint16_t[3]) { top, top + i + 1, top + i + 2 }, 3 * sizeof(uint16_t));
|
||||
indices += 3;
|
||||
}
|
||||
|
||||
if (capped && r2 != 0.f) {
|
||||
memcpy(indices, (uint16_t[3]) { bot, bot + i + 1, bot + i + 2 }, 3 * sizeof(uint16_t));
|
||||
indices += 3;
|
||||
}
|
||||
}
|
||||
|
||||
I += vertexCount;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_SPHERE: {
|
||||
int segments = params->sphere.segments;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j <= segments; j++) {
|
||||
float v = j / (float) segments;
|
||||
float sinV = sinf(v * (float) M_PI);
|
||||
float cosV = cosf(v * (float) M_PI);
|
||||
for (int k = 0; k <= segments; k++) {
|
||||
float u = k / (float) segments;
|
||||
float x = sinf(u * 2.f * (float) M_PI) * sinV;
|
||||
float y = cosV;
|
||||
float z = -cosf(u * 2.f * (float) M_PI) * sinV;
|
||||
memcpy(vertices, ((float[8]) { x, y, z, x, y, z, u, 1.f - v }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < segments; j++) {
|
||||
uint16_t offset0 = j * (segments + 1) + I;
|
||||
uint16_t offset1 = (j + 1) * (segments + 1) + I;
|
||||
for (int k = 0; k < segments; k++) {
|
||||
uint16_t i0 = offset0 + k;
|
||||
uint16_t i1 = offset1 + k;
|
||||
memcpy(indices, ((uint16_t[]) { i0, i1, i0 + 1, i1, i1 + 1, i0 + 1 }), 6 * sizeof(uint16_t));
|
||||
indices += 6;
|
||||
}
|
||||
}
|
||||
|
||||
I += vertexCount;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case BATCH_SKYBOX:
|
||||
for (int i = 0; i < n; i++) {
|
||||
memcpy(vertices, (float[32]) {
|
||||
-1, 1, 1, 0, 0, 0, 0, 0,
|
||||
-1, -1, 1, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 0, 0, 0, 0, 0,
|
||||
1, -1, 1, 0, 0, 0, 0, 0
|
||||
}, 32 * sizeof(float));
|
||||
vertices += 32;
|
||||
}
|
||||
break;
|
||||
|
||||
case BATCH_FILL:
|
||||
for (int i = 0; i < n; i++) {
|
||||
float u = params->fill.u;
|
||||
float v = params->fill.v;
|
||||
float w = params->fill.w;
|
||||
float h = params->fill.h;
|
||||
memcpy(vertices, (float[32]) {
|
||||
-1, 1, 0, 0, 0, 0, u, v + h,
|
||||
-1, -1, 0, 0, 0, 0, u, v,
|
||||
1, 1, 0, 0, 0, 0, u + w, v + h,
|
||||
1, -1, 0, 0, 0, 0, u + w, v
|
||||
}, 32 * sizeof(float));
|
||||
vertices += 32;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
if (vertices) {
|
||||
memcpy(vertices, (float[32]) {
|
||||
-1, 1, 0, 0, 0, 0, u, v + h,
|
||||
-1, -1, 0, 0, 0, 0, u, v,
|
||||
1, 1, 0, 0, 0, 0, u + w, v + h,
|
||||
1, -1, 0, 0, 0, 0, u + w, v
|
||||
}, 32 * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ typedef union {
|
|||
typedef struct {
|
||||
BatchType type;
|
||||
BatchParams params;
|
||||
DrawMode drawMode;
|
||||
DefaultShader shader;
|
||||
Pipeline* pipeline;
|
||||
Material* material;
|
||||
|
@ -143,11 +144,13 @@ typedef struct {
|
|||
float** vertices;
|
||||
uint16_t** indices;
|
||||
uint16_t* baseVertex;
|
||||
bool instanced;
|
||||
} BatchRequest;
|
||||
|
||||
typedef struct {
|
||||
BatchType type;
|
||||
BatchParams params;
|
||||
DrawMode drawMode;
|
||||
Canvas* canvas;
|
||||
Shader* shader;
|
||||
Pipeline pipeline;
|
||||
|
@ -159,6 +162,7 @@ typedef struct {
|
|||
uint32_t drawStart;
|
||||
uint32_t drawCount;
|
||||
DrawData* drawData;
|
||||
bool instanced;
|
||||
} Batch;
|
||||
|
||||
typedef struct {
|
||||
|
@ -187,7 +191,6 @@ typedef struct {
|
|||
Buffer* buffers[MAX_BUFFER_ROLES];
|
||||
uint32_t cursors[MAX_BUFFER_ROLES];
|
||||
void* locks[MAX_BUFFER_ROLES][MAX_LOCKS];
|
||||
Batch cachedGeometry;
|
||||
Batch batches[MAX_BATCHES];
|
||||
uint8_t batchCount;
|
||||
} GraphicsState;
|
||||
|
|
Loading…
Reference in New Issue