Organize drawing code;

This commit is contained in:
bjorn 2018-03-22 08:45:05 -07:00
parent 8e5061f918
commit c0ea3240c3
6 changed files with 212 additions and 232 deletions

View File

@ -57,8 +57,7 @@ int l_lovrMeshDrawInstanced(lua_State* L) {
int instances = luaL_checkinteger(L, 2);
float transform[16];
luax_readtransform(L, 3, transform, 1);
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshDraw(mesh, transform, NULL, instances);
lovrGraphicsDraw(mesh, transform, SHADER_DEFAULT, instances);
return 0;
}

View File

@ -59,7 +59,6 @@ void lovrGraphicsReset() {
int h = lovrGraphicsGetHeight();
state.transform = 0;
state.layer = 0;
state.defaultShader = SHADER_DEFAULT;
mat4_perspective(state.layers[state.layer].projections, .01f, 100.f, 67 * M_PI / 180., (float) w / h / 2.);
mat4_perspective(state.layers[state.layer].projections + 16, .01f, 100.f, 67 * M_PI / 180., (float) w / h / 2.);
mat4_identity(state.layers[state.layer].views);
@ -106,102 +105,6 @@ void lovrGraphicsPresent() {
state.program = -1; // Fixes a driver bug with instancing seen on macOS
}
void lovrGraphicsPrepare(Material* material, float* pose) {
Shader* shader = lovrGraphicsGetActiveShader();
if (!shader) {
shader = state.defaultShaders[state.defaultShader] = lovrShaderCreateDefault(state.defaultShader);
}
// Layer
Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas;
int w = canvas ? canvas->texture.width : lovrGraphicsGetWidth();
int h = canvas ? canvas->texture.height : lovrGraphicsGetHeight();
lovrGraphicsBindFramebuffer(canvas ? canvas->framebuffer : 0);
lovrGraphicsSetViewport(0, 0, w, h);
lovrGraphicsBindUniformBuffer(state.cameraUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 16 * sizeof(float), &layer); // TODO
// Transforms
mat4 model = state.transforms[state.transform];
lovrShaderSetMatrix(shader, "lovrModel", model, 16);
float transforms[32];
mat4_multiply(mat4_set(transforms + 0, layer.views + 0), model);
mat4_multiply(mat4_set(transforms + 16, layer.views + 16), model);
lovrShaderSetMatrix(shader, "lovrTransforms", transforms, 32);
if (lovrShaderGetUniform(shader, "lovrNormalMatrices")) {
if (mat4_invert(transforms)) {
mat4_transpose(transforms);
} else {
mat4_identity(transforms);
}
if (mat4_invert(transforms + 16)) {
mat4_transpose(transforms + 16);
} else {
mat4_identity(transforms + 16);
}
float normalMatrix[18] = {
transforms[0], transforms[1], transforms[2],
transforms[4], transforms[5], transforms[6],
transforms[8], transforms[9], transforms[10],
transforms[16], transforms[17], transforms[18],
transforms[20], transforms[21], transforms[22],
transforms[24], transforms[25], transforms[26]
};
lovrShaderSetMatrix(shader, "lovrNormalMatrices", normalMatrix, 18);
}
// Color
Color color = state.color;
gammaCorrectColor(&color);
float data[4] = { color.r, color.g, color.b, color.a };
lovrShaderSetFloat(shader, "lovrColor", data, 4);
// Point size
lovrShaderSetFloat(shader, "lovrPointSize", &state.pointSize, 1);
// Pose
if (pose) {
lovrShaderSetMatrix(shader, "lovrPose", pose, MAX_BONES * 16);
} else {
float identity[16];
mat4_identity(identity);
lovrShaderSetMatrix(shader, "lovrPose", identity, 16);
}
// Material
if (!material) {
material = lovrGraphicsGetDefaultMaterial();
}
for (int i = 0; i < MAX_MATERIAL_SCALARS; i++) {
float value = lovrMaterialGetScalar(material, i);
lovrShaderSetFloat(shader, lovrShaderScalarUniforms[i], &value, 1);
}
for (int i = 0; i < MAX_MATERIAL_COLORS; i++) {
Color color = lovrMaterialGetColor(material, i);
gammaCorrectColor(&color);
float data[4] = { color.r, color.g, color.b, color.a };
lovrShaderSetFloat(shader, lovrShaderColorUniforms[i], data, 4);
}
for (int i = 0; i < MAX_MATERIAL_TEXTURES; i++) {
Texture* texture = lovrMaterialGetTexture(material, i);
lovrShaderSetTexture(shader, lovrShaderTextureUniforms[i], &texture, 1);
}
lovrGraphicsUseProgram(shader->program);
lovrShaderBind(shader);
}
void lovrGraphicsCreateWindow(int w, int h, bool fullscreen, int msaa, const char* title, const char* icon) {
lovrAssert(!state.window, "Window is already created");
@ -635,21 +538,19 @@ VertexPointer lovrGraphicsGetVertexPointer(uint32_t count) {
}
void lovrGraphicsPoints(uint32_t count) {
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetDrawMode(state.mesh, MESH_POINTS);
lovrMeshSetDrawRange(state.mesh, 0, count);
lovrMeshSetMaterial(state.mesh, NULL);
lovrMeshWriteIndices(state.mesh, 0, 0);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1);
}
void lovrGraphicsLine(uint32_t count) {
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetDrawMode(state.mesh, MESH_LINE_STRIP);
lovrMeshSetDrawRange(state.mesh, 0, count);
lovrMeshSetMaterial(state.mesh, NULL);
lovrMeshWriteIndices(state.mesh, 0, 0);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1);
}
void lovrGraphicsTriangle(DrawMode mode, Material* material, float points[9]) {
@ -680,9 +581,8 @@ void lovrGraphicsTriangle(DrawMode mode, Material* material, float points[9]) {
}
lovrMeshSetDrawRange(state.mesh, 0, 3);
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1);
}
void lovrGraphicsPlane(DrawMode mode, Material* material, mat4 transform) {
@ -710,11 +610,10 @@ void lovrGraphicsPlane(DrawMode mode, Material* material, mat4 transform) {
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP);
}
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshWriteIndices(state.mesh, 0, 0);
lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrMeshDraw(state.mesh, transform, NULL, 1);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1);
}
void lovrGraphicsBox(DrawMode mode, Material* material, mat4 transform) {
@ -795,9 +694,8 @@ void lovrGraphicsBox(DrawMode mode, Material* material, mat4 transform) {
lovrMeshSetDrawRange(state.mesh, 0, 26);
}
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshDraw(state.mesh, transform, NULL, 1);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1);
}
void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 transform, float theta1, float theta2, int segments) {
@ -841,11 +739,10 @@ void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 tr
theta += angleShift;
}
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, mode == DRAW_MODE_LINE ? (arcMode == ARC_MODE_OPEN ? MESH_LINE_STRIP : MESH_LINE_LOOP) : MESH_TRIANGLE_FAN);
lovrMeshSetDrawRange(state.mesh, 0, count);
lovrMeshDraw(state.mesh, transform, NULL, 1);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1);
}
void lovrGraphicsCircle(DrawMode mode, Material* material, mat4 transform, int segments) {
@ -942,11 +839,10 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
#undef PUSH_CYLINDER_VERTEX
#undef PUSH_CYLINDER_TRIANGLE
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, indexCount);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1);
}
void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
@ -988,11 +884,10 @@ void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
}
}
lovrGraphicsSetDefaultShader(SHADER_DEFAULT);
lovrMeshSetDrawMode(state.mesh, GL_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, segments * segments * 6);
lovrMeshSetMaterial(state.mesh, material);
lovrMeshDraw(state.mesh, transform, NULL, 1);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1);
}
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az) {
@ -1006,9 +901,9 @@ void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float
TextureType type = texture->type;
lovrAssert(type == TEXTURE_CUBE || type == TEXTURE_2D, "Only 2D and cube textures can be used as skyboxes");
MaterialTexture materialTexture = type == TEXTURE_CUBE ? TEXTURE_ENVIRONMENT_MAP : TEXTURE_DIFFUSE;
DefaultShader shader = type == TEXTURE_CUBE ? SHADER_CUBE : SHADER_PANO;
Winding winding = state.winding;
lovrGraphicsSetWinding(WINDING_COUNTERCLOCKWISE);
lovrGraphicsSetDefaultShader(type == TEXTURE_CUBE ? SHADER_CUBE : SHADER_PANO);
Material* material = lovrGraphicsGetDefaultMaterial();
lovrMaterialSetTexture(material, materialTexture, texture);
VertexPointer vertexPointer = lovrGraphicsGetVertexPointer(4);
@ -1017,7 +912,7 @@ void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float
lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP);
lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, shader, 1);
lovrMaterialSetTexture(material, materialTexture, NULL);
lovrGraphicsSetWinding(winding);
}
@ -1036,7 +931,6 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
lovrGraphicsMatrixTransform(transform);
lovrGraphicsScale(scale, scale, scale);
lovrGraphicsTranslate(0, offsety, 0);
lovrGraphicsSetDefaultShader(SHADER_FONT);
Material* material = lovrGraphicsGetDefaultMaterial();
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, font->texture);
CompareMode mode;
@ -1046,7 +940,7 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, vertexCount);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_FONT, 1);
lovrGraphicsSetDepthTest(mode, write);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL);
lovrGraphicsPop();
@ -1088,7 +982,6 @@ void lovrGraphicsFill(Texture* texture) {
bool write;
lovrGraphicsGetDepthTest(&mode, &write);
lovrGraphicsSetDepthTest(COMPARE_NONE, false);
lovrGraphicsSetDefaultShader(SHADER_FILL);
Material* material = lovrGraphicsGetDefaultMaterial();
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, texture);
VertexPointer vertexPointer = lovrGraphicsGetVertexPointer(4);
@ -1098,11 +991,137 @@ void lovrGraphicsFill(Texture* texture) {
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP);
lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL);
lovrMeshDraw(state.mesh, NULL, NULL, 1);
lovrGraphicsDraw(state.mesh, NULL, SHADER_FILL, 1);
lovrGraphicsSetDepthTest(mode, write);
}
// Internal State
// Internal
void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader defaultShader, int instances) {
Shader* shader = state.shader ? state.shader : state.defaultShaders[defaultShader];
if (!shader) {
shader = state.defaultShaders[defaultShader] = lovrShaderCreateDefault(defaultShader);
}
// Layer
Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas;
int w = canvas ? canvas->texture.width : lovrGraphicsGetWidth();
int h = canvas ? canvas->texture.height : lovrGraphicsGetHeight();
lovrGraphicsBindFramebuffer(canvas ? canvas->framebuffer : 0);
lovrGraphicsSetViewport(0, 0, w, h);
lovrGraphicsBindUniformBuffer(state.cameraUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 16 * sizeof(float), &layer); // TODO
// Transforms
if (transform) {
lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
}
mat4 model = state.transforms[state.transform];
lovrShaderSetMatrix(shader, "lovrModel", model, 16);
float transforms[32];
mat4_multiply(mat4_set(transforms + 0, layer.views + 0), model);
mat4_multiply(mat4_set(transforms + 16, layer.views + 16), model);
lovrShaderSetMatrix(shader, "lovrTransforms", transforms, 32);
if (lovrShaderGetUniform(shader, "lovrNormalMatrices")) {
if (mat4_invert(transforms)) {
mat4_transpose(transforms);
} else {
mat4_identity(transforms);
}
if (mat4_invert(transforms + 16)) {
mat4_transpose(transforms + 16);
} else {
mat4_identity(transforms + 16);
}
float normalMatrix[18] = {
transforms[0], transforms[1], transforms[2],
transforms[4], transforms[5], transforms[6],
transforms[8], transforms[9], transforms[10],
transforms[16], transforms[17], transforms[18],
transforms[20], transforms[21], transforms[22],
transforms[24], transforms[25], transforms[26]
};
lovrShaderSetMatrix(shader, "lovrNormalMatrices", normalMatrix, 18);
}
// Color
Color color = state.color;
gammaCorrectColor(&color);
float data[4] = { color.r, color.g, color.b, color.a };
lovrShaderSetFloat(shader, "lovrColor", data, 4);
// Point size
lovrShaderSetFloat(shader, "lovrPointSize", &state.pointSize, 1);
// Pose
float* pose = lovrMeshGetPose(mesh);
if (pose) {
lovrShaderSetMatrix(shader, "lovrPose", pose, MAX_BONES * 16);
} else {
float identity[16];
mat4_identity(identity);
lovrShaderSetMatrix(shader, "lovrPose", identity, 16);
}
// Material
Material* material = lovrMeshGetMaterial(mesh);
if (!material) {
material = lovrGraphicsGetDefaultMaterial();
}
for (int i = 0; i < MAX_MATERIAL_SCALARS; i++) {
float value = lovrMaterialGetScalar(material, i);
lovrShaderSetFloat(shader, lovrShaderScalarUniforms[i], &value, 1);
}
for (int i = 0; i < MAX_MATERIAL_COLORS; i++) {
Color color = lovrMaterialGetColor(material, i);
gammaCorrectColor(&color);
float data[4] = { color.r, color.g, color.b, color.a };
lovrShaderSetFloat(shader, lovrShaderColorUniforms[i], data, 4);
}
for (int i = 0; i < MAX_MATERIAL_TEXTURES; i++) {
Texture* texture = lovrMaterialGetTexture(material, i);
lovrShaderSetTexture(shader, lovrShaderTextureUniforms[i], &texture, 1);
}
lovrGraphicsUseProgram(shader->program);
lovrShaderBind(shader);
lovrGraphicsBindVertexArray(mesh->vao);
lovrMeshUnmapVertices(mesh);
lovrMeshUnmapIndices(mesh);
lovrMeshBind(mesh, shader);
size_t start = mesh->rangeStart;
if (mesh->indexCount > 0) {
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->indexCount;
GLenum indexType = mesh->indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
size_t offset = start * mesh->indexSize;
glDrawElementsInstanced(mesh->drawMode, count, indexType, (GLvoid*) offset, instances * 2);
} else {
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->count;
glDrawArraysInstanced(mesh->drawMode, start, count, instances * 2);
}
if (transform) {
lovrGraphicsPop();
}
state.stats.drawCalls++;
}
void lovrGraphicsPushLayer(Layer layer) {
if (++state.layer >= MAX_LAYERS) {
lovrThrow("Layer overflow");
@ -1154,14 +1173,6 @@ Material* lovrGraphicsGetDefaultMaterial() {
return state.defaultMaterial;
}
void lovrGraphicsSetDefaultShader(DefaultShader shader) {
state.defaultShader = shader;
}
Shader* lovrGraphicsGetActiveShader() {
return state.shader ? state.shader : state.defaultShaders[state.defaultShader];
}
void lovrGraphicsUseProgram(uint32_t program) {
if (state.program != program) {
state.program = program;
@ -1204,14 +1215,3 @@ void lovrGraphicsBindIndexBuffer(uint32_t indexBuffer) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
}
}
void lovrGraphicsDrawArrays(GLenum mode, size_t start, size_t count, int instances) {
glDrawArraysInstanced(mode, start, count, instances * 2);
state.stats.drawCalls++;
}
void lovrGraphicsDrawElements(GLenum mode, size_t count, size_t indexSize, size_t offset, int instances) {
GLenum indexType = indexSize == sizeof(uint16_t) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
glDrawElementsInstanced(mode, count, indexType, (GLvoid*) offset, instances * 2);
state.stats.drawCalls++;
}

View File

@ -93,7 +93,6 @@ typedef struct {
bool initialized;
GLFWwindow* window;
Shader* defaultShaders[DEFAULT_SHADER_COUNT];
DefaultShader defaultShader;
Material* defaultMaterial;
Font* defaultFont;
Texture* defaultTexture;
@ -141,7 +140,6 @@ void lovrGraphicsDestroy();
void lovrGraphicsReset();
void lovrGraphicsClear(bool clearColor, bool clearDepth, bool clearStencil, Color color, float depth, int stencil);
void lovrGraphicsPresent();
void lovrGraphicsPrepare(Material* material, float* pose);
void lovrGraphicsCreateWindow(int w, int h, bool fullscreen, int msaa, const char* title, const char* icon);
int lovrGraphicsGetWidth();
int lovrGraphicsGetHeight();
@ -204,7 +202,8 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata);
void lovrGraphicsFill(Texture* texture);
// Internal State
// Internal
void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader shader, int instances);
VertexPointer lovrGraphicsGetVertexPointer(uint32_t capacity);
void lovrGraphicsPushLayer(Layer layer);
void lovrGraphicsPopLayer();
@ -212,13 +211,9 @@ void lovrGraphicsSetViewport(int x, int y, int w, int h);
Texture* lovrGraphicsGetTexture(int slot);
void lovrGraphicsBindTexture(Texture* texture, TextureType type, int slot);
Material* lovrGraphicsGetDefaultMaterial();
void lovrGraphicsSetDefaultShader(DefaultShader defaultShader);
Shader* lovrGraphicsGetActiveShader();
void lovrGraphicsUseProgram(uint32_t program);
void lovrGraphicsBindFramebuffer(uint32_t framebuffer);
void lovrGraphicsBindVertexArray(uint32_t vao);
void lovrGraphicsBindVertexBuffer(uint32_t vbo);
void lovrGraphicsBindUniformBuffer(uint32_t ubo);
void lovrGraphicsBindIndexBuffer(uint32_t ibo);
void lovrGraphicsDrawArrays(GLenum mode, size_t start, size_t count, int instances);
void lovrGraphicsDrawElements(GLenum mode, size_t count, size_t indexSize, size_t offset, int instances);

View File

@ -3,68 +3,6 @@
#include <stdlib.h>
#include <stdio.h>
static void lovrMeshBindAttributes(Mesh* mesh) {
const char* key;
map_iter_t iter = map_iter(&mesh->attachments);
Shader* shader = lovrGraphicsGetActiveShader();
MeshAttachment layout[MAX_ATTACHMENTS];
memset(layout, 0, MAX_ATTACHMENTS * sizeof(MeshAttachment));
while ((key = map_next(&mesh->attachments, &iter)) != NULL) {
int location = lovrShaderGetAttributeId(shader, key);
if (location >= 0) {
MeshAttachment* attachment = map_get(&mesh->attachments, key);
layout[location] = *attachment;
}
}
for (int i = 0; i < MAX_ATTACHMENTS; i++) {
MeshAttachment previous = mesh->layout[i];
MeshAttachment current = layout[i];
if (!memcmp(&previous, &current, sizeof(MeshAttachment))) {
continue;
}
if (previous.enabled != current.enabled) {
if (current.enabled) {
glEnableVertexAttribArray(i);
} else {
glDisableVertexAttribArray(i);
mesh->layout[i] = current;
continue;
}
}
if (previous.divisor != current.divisor) {
glVertexAttribDivisor(i, current.divisor);
}
if (previous.mesh != current.mesh || previous.attributeIndex != current.attributeIndex) {
lovrGraphicsBindVertexBuffer(current.mesh->vbo);
VertexFormat* format = &current.mesh->format;
Attribute attribute = format->attributes[current.attributeIndex];
switch (attribute.type) {
case ATTR_FLOAT:
glVertexAttribPointer(i, attribute.count, GL_FLOAT, GL_TRUE, format->stride, (void*) attribute.offset);
break;
case ATTR_BYTE:
glVertexAttribPointer(i, attribute.count, GL_UNSIGNED_BYTE, GL_TRUE, format->stride, (void*) attribute.offset);
break;
case ATTR_INT:
glVertexAttribIPointer(i, attribute.count, GL_UNSIGNED_INT, format->stride, (void*) attribute.offset);
break;
}
}
mesh->layout[i] = current;
}
}
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, MeshUsage usage) {
Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy);
if (!mesh) return NULL;
@ -135,30 +73,64 @@ void lovrMeshDetachAttribute(Mesh* mesh, const char* name) {
map_remove(&mesh->attachments, name);
}
void lovrMeshDraw(Mesh* mesh, mat4 transform, float* pose, int instances) {
lovrMeshUnmapVertices(mesh);
lovrMeshUnmapIndices(mesh);
void lovrMeshBind(Mesh* mesh, Shader* shader) {
const char* key;
map_iter_t iter = map_iter(&mesh->attachments);
if (transform) {
lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
MeshAttachment layout[MAX_ATTACHMENTS];
memset(layout, 0, MAX_ATTACHMENTS * sizeof(MeshAttachment));
while ((key = map_next(&mesh->attachments, &iter)) != NULL) {
int location = lovrShaderGetAttributeId(shader, key);
if (location >= 0) {
MeshAttachment* attachment = map_get(&mesh->attachments, key);
layout[location] = *attachment;
}
}
lovrGraphicsPrepare(mesh->material, pose);
lovrGraphicsBindVertexArray(mesh->vao);
lovrMeshBindAttributes(mesh);
size_t start = mesh->rangeStart;
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->count;
if (mesh->indexCount > 0) {
size_t offset = start * mesh->indexSize;
count = mesh->rangeCount ? mesh->rangeCount : mesh->indexCount;
lovrGraphicsDrawElements(mesh->drawMode, count, mesh->indexSize, offset, instances);
} else {
lovrGraphicsDrawArrays(mesh->drawMode, start, count, instances);
}
for (int i = 0; i < MAX_ATTACHMENTS; i++) {
MeshAttachment previous = mesh->layout[i];
MeshAttachment current = layout[i];
if (transform) {
lovrGraphicsPop();
if (!memcmp(&previous, &current, sizeof(MeshAttachment))) {
continue;
}
if (previous.enabled != current.enabled) {
if (current.enabled) {
glEnableVertexAttribArray(i);
} else {
glDisableVertexAttribArray(i);
mesh->layout[i] = current;
continue;
}
}
if (previous.divisor != current.divisor) {
glVertexAttribDivisor(i, current.divisor);
}
if (previous.mesh != current.mesh || previous.attributeIndex != current.attributeIndex) {
lovrGraphicsBindVertexBuffer(current.mesh->vbo);
VertexFormat* format = &current.mesh->format;
Attribute attribute = format->attributes[current.attributeIndex];
switch (attribute.type) {
case ATTR_FLOAT:
glVertexAttribPointer(i, attribute.count, GL_FLOAT, GL_TRUE, format->stride, (void*) attribute.offset);
break;
case ATTR_BYTE:
glVertexAttribPointer(i, attribute.count, GL_UNSIGNED_BYTE, GL_TRUE, format->stride, (void*) attribute.offset);
break;
case ATTR_INT:
glVertexAttribIPointer(i, attribute.count, GL_UNSIGNED_INT, format->stride, (void*) attribute.offset);
break;
}
}
mesh->layout[i] = current;
}
}
@ -215,6 +187,14 @@ void lovrMeshSetMaterial(Mesh* mesh, Material* material) {
}
}
float* lovrMeshGetPose(Mesh* mesh) {
return mesh->pose;
}
void lovrMeshSetPose(Mesh* mesh, float* pose) {
mesh->pose = pose;
}
VertexPointer lovrMeshMapVertices(Mesh* mesh, uint32_t start, uint32_t count, bool read, bool write) {
#ifdef EMSCRIPTEN
mesh->mappedVertices = true;

View File

@ -1,4 +1,5 @@
#include "graphics/material.h"
#include "graphics/shader.h"
#include "data/vertexData.h"
#include "math/math.h"
#include "lib/glfw.h"
@ -59,6 +60,7 @@ struct Mesh {
GLuint vbo;
GLuint ibo;
Material* material;
float* pose;
map_attachment_t attachments;
MeshAttachment layout[MAX_ATTACHMENTS];
bool isAttachment;
@ -68,7 +70,7 @@ Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode,
void lovrMeshDestroy(void* ref);
void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor);
void lovrMeshDetachAttribute(Mesh* mesh, const char* name);
void lovrMeshDraw(Mesh* mesh, mat4 transform, float* pose, int instances);
void lovrMeshBind(Mesh* mesh, Shader* shader);
VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh);
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);
void lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode);
@ -79,6 +81,8 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count);
void lovrMeshSetDrawRange(Mesh* mesh, int start, int count);
Material* lovrMeshGetMaterial(Mesh* mesh);
void lovrMeshSetMaterial(Mesh* mesh, Material* material);
float* lovrMeshGetPose(Mesh* mesh);
void lovrMeshSetPose(Mesh* mesh, float* pose);
VertexPointer lovrMeshMapVertices(Mesh* mesh, uint32_t start, uint32_t count, bool read, bool write);
void lovrMeshUnmapVertices(Mesh* mesh);
IndexPointer lovrMeshReadIndices(Mesh* mesh, uint32_t* count, size_t* size);

View File

@ -38,7 +38,8 @@ static void renderNode(Model* model, int nodeIndex, int instances) {
}
lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount);
lovrMeshDraw(model->mesh, NULL, (float*) model->pose, instances);
lovrMeshSetPose(model->mesh, (float*) model->pose);
lovrGraphicsDraw(model->mesh, NULL, SHADER_DEFAULT, instances);
}
lovrGraphicsPop();
@ -163,6 +164,7 @@ void lovrModelDraw(Model* model, mat4 transform, int instances) {
lovrGraphicsMatrixTransform(transform);
renderNode(model, 0, instances);
lovrGraphicsPop();
lovrMeshSetPose(model->mesh, NULL);
}
Animator* lovrModelGetAnimator(Model* model) {