Clean up drawing;

This commit is contained in:
bjorn 2018-07-13 13:53:55 -07:00
parent 322c0bdef7
commit e6e8e137c0
9 changed files with 179 additions and 163 deletions

View File

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

View File

@ -1,35 +1,43 @@
#include "graphics/canvas.h"
#include "graphics/material.h"
#include "graphics/mesh.h" #include "graphics/mesh.h"
#include "graphics/shader.h" #include "graphics/shader.h"
#include "graphics/texture.h" #include "graphics/texture.h"
#include "math/math.h"
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#pragma once #pragma once
#define MAX_CANVASES 4
typedef struct { typedef struct {
int shaderSwitches; int shaderSwitches;
int drawCalls; int drawCalls;
} GpuStats; } GpuStats;
typedef struct { typedef struct {
float projection[16];
float view[16];
uint32_t viewport[4];
Canvas* canvas[MAX_CANVASES];
int canvasCount;
bool user;
} Layer;
typedef struct {
Layer layer;
Mesh* mesh; Mesh* mesh;
mat4 transform;
Material* material;
Color color;
float pointSize;
Shader* shader; Shader* shader;
int instances; int instances;
/* /*
eventually: eventually:
Canvas* canvas;
uint32_t viewport[4];
mat4 view;
mat4 projection;
mat4 model;
Color color;
float pointSize;
Material* material;
struct { struct {
CompareMode test; CompareMode test;
bool write; bool write;

View File

@ -93,14 +93,13 @@ void lovrGraphicsReset() {
void lovrGraphicsClear(bool clearColor, bool clearDepth, bool clearStencil, Color color, float depth, int stencil) { void lovrGraphicsClear(bool clearColor, bool clearDepth, bool clearStencil, Color color, float depth, int stencil) {
Layer layer = state.layers[state.layer]; Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas; gpuBindFramebuffer(layer.canvasCount > 0 ? lovrCanvasGetId(layer.canvas[0]) : 0);
gpuBindFramebuffer(canvas ? lovrCanvasGetId(canvas) : 0);
if (clearColor) { if (clearColor) {
gammaCorrectColor(&color); gammaCorrectColor(&color);
float c[4] = { color.r, color.g, color.b, color.a }; float c[4] = { color.r, color.g, color.b, color.a };
glClearBufferfv(GL_COLOR, 0, c); glClearBufferfv(GL_COLOR, 0, c);
for (int i = 1; i < state.canvasCount; i++) { for (int i = 1; i < layer.canvasCount; i++) {
glClearBufferfv(GL_COLOR, i, c); glClearBufferfv(GL_COLOR, i, c);
} }
} }
@ -263,46 +262,21 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
} }
void lovrGraphicsGetCanvas(Canvas** canvas, int* count) { void lovrGraphicsGetCanvas(Canvas** canvas, int* count) {
*count = state.canvasCount; Layer layer = state.layers[state.layer];
memcpy(canvas, state.canvas, state.canvasCount * sizeof(Canvas*)); if (layer.user) {
*count = layer.canvasCount;
memcpy(canvas, layer.canvas, layer.canvasCount * sizeof(Canvas*));
} else {
*count = 0;
}
} }
void lovrGraphicsSetCanvas(Canvas** canvas, int count) { void lovrGraphicsSetCanvas(Canvas** canvas, int count) {
if (count == state.canvasCount && !memcmp(state.canvas, canvas, count * sizeof(Canvas*))) { if (state.layers[state.layer].user) {
return; lovrGraphicsPopLayer();
} }
lovrAssert(count <= MAX_CANVASES, "Attempt to simultaneously render to %d canvases (the maximum is %d)", count, MAX_CANVASES); lovrGraphicsPushLayer(canvas, count, true);
if (state.canvasCount > 0) {
lovrCanvasResolve(state.canvas[0]);
}
for (int i = 0; i < count; i++) {
lovrRetain(canvas[i]);
}
for (int i = 0; i < state.canvasCount; i++) {
lovrRelease(state.canvas[i]);
}
if (count > 0) {
memcpy(state.canvas, canvas, count * sizeof(Canvas*));
gpuBindFramebuffer(lovrCanvasGetId(canvas[0]));
GLenum buffers[MAX_CANVASES];
for (int i = 0; i < count; i++) {
buffers[i] = GL_COLOR_ATTACHMENT0 + i;
glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, lovrTextureGetId((Texture*) canvas[i]), 0);
}
glDrawBuffers(count, buffers);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
lovrAssert(status != GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "All multicanvas canvases must have the same dimensions");
lovrAssert(status == GL_FRAMEBUFFER_COMPLETE, "Unable to bind framebuffer");
}
state.canvasCount = count;
} }
Color lovrGraphicsGetColor() { Color lovrGraphicsGetColor() {
@ -542,7 +516,7 @@ void lovrGraphicsPoints(uint32_t count) {
lovrMeshSetDrawRange(state.mesh, 0, count); lovrMeshSetDrawRange(state.mesh, 0, count);
lovrMeshSetMaterial(state.mesh, NULL); lovrMeshSetMaterial(state.mesh, NULL);
lovrMeshWriteIndices(state.mesh, 0, 0); lovrMeshWriteIndices(state.mesh, 0, 0);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1); lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
} }
void lovrGraphicsLine(uint32_t count) { void lovrGraphicsLine(uint32_t count) {
@ -550,7 +524,7 @@ void lovrGraphicsLine(uint32_t count) {
lovrMeshSetDrawRange(state.mesh, 0, count); lovrMeshSetDrawRange(state.mesh, 0, count);
lovrMeshSetMaterial(state.mesh, NULL); lovrMeshSetMaterial(state.mesh, NULL);
lovrMeshWriteIndices(state.mesh, 0, 0); lovrMeshWriteIndices(state.mesh, 0, 0);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1); lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
} }
void lovrGraphicsTriangle(DrawMode mode, Material* material, float points[9]) { void lovrGraphicsTriangle(DrawMode mode, Material* material, float points[9]) {
@ -582,7 +556,7 @@ void lovrGraphicsTriangle(DrawMode mode, Material* material, float points[9]) {
lovrMeshSetDrawRange(state.mesh, 0, 3); lovrMeshSetDrawRange(state.mesh, 0, 3);
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1); lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
} }
void lovrGraphicsPlane(DrawMode mode, Material* material, mat4 transform) { void lovrGraphicsPlane(DrawMode mode, Material* material, mat4 transform) {
@ -613,7 +587,10 @@ void lovrGraphicsPlane(DrawMode mode, Material* material, mat4 transform) {
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshWriteIndices(state.mesh, 0, 0); lovrMeshWriteIndices(state.mesh, 0, 0);
lovrMeshSetDrawRange(state.mesh, 0, 4); lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1); lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
lovrGraphicsPop();
} }
void lovrGraphicsBox(DrawMode mode, Material* material, mat4 transform) { void lovrGraphicsBox(DrawMode mode, Material* material, mat4 transform) {
@ -695,7 +672,10 @@ void lovrGraphicsBox(DrawMode mode, Material* material, mat4 transform) {
} }
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1); lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
lovrGraphicsPop();
} }
void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 transform, float theta1, float theta2, int segments) { void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 transform, float theta1, float theta2, int segments) {
@ -742,7 +722,10 @@ void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 tr
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, mode == DRAW_MODE_LINE ? (arcMode == ARC_MODE_OPEN ? MESH_LINE_STRIP : MESH_LINE_LOOP) : MESH_TRIANGLE_FAN); 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); lovrMeshSetDrawRange(state.mesh, 0, count);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1); lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
lovrGraphicsPop();
} }
void lovrGraphicsCircle(DrawMode mode, Material* material, mat4 transform, int segments) { void lovrGraphicsCircle(DrawMode mode, Material* material, mat4 transform, int segments) {
@ -842,7 +825,7 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES); lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, indexCount); lovrMeshSetDrawRange(state.mesh, 0, indexCount);
lovrGraphicsDraw(state.mesh, NULL, SHADER_DEFAULT, 1); lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
} }
void lovrGraphicsSphere(Material* material, mat4 transform, int segments) { void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
@ -887,7 +870,10 @@ void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
lovrMeshSetDrawMode(state.mesh, GL_TRIANGLES); lovrMeshSetDrawMode(state.mesh, GL_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, segments * segments * 6); lovrMeshSetDrawRange(state.mesh, 0, segments * segments * 6);
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrGraphicsDraw(state.mesh, transform, SHADER_DEFAULT, 1); lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
lovrGraphicsDraw(state.mesh, SHADER_DEFAULT, 1);
lovrGraphicsPop();
} }
void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az) { void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float az) {
@ -912,7 +898,7 @@ void lovrGraphicsSkybox(Texture* texture, float angle, float ax, float ay, float
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP); lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP);
lovrMeshSetDrawRange(state.mesh, 0, 4); lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrGraphicsDraw(state.mesh, NULL, shader, 1); lovrGraphicsDraw(state.mesh, shader, 1);
lovrMaterialSetTexture(material, materialTexture, NULL); lovrMaterialSetTexture(material, materialTexture, NULL);
lovrGraphicsSetWinding(winding); lovrGraphicsSetWinding(winding);
} }
@ -940,7 +926,7 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES); lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLES);
lovrMeshSetDrawRange(state.mesh, 0, vertexCount); lovrMeshSetDrawRange(state.mesh, 0, vertexCount);
lovrGraphicsDraw(state.mesh, NULL, SHADER_FONT, 1); lovrGraphicsDraw(state.mesh, SHADER_FONT, 1);
lovrGraphicsSetDepthTest(mode, write); lovrGraphicsSetDepthTest(mode, write);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL); lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL);
lovrGraphicsPop(); lovrGraphicsPop();
@ -1000,70 +986,19 @@ void lovrGraphicsFill(Texture* texture) {
lovrMeshSetMaterial(state.mesh, material); lovrMeshSetMaterial(state.mesh, material);
lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP); lovrMeshSetDrawMode(state.mesh, MESH_TRIANGLE_STRIP);
lovrMeshSetDrawRange(state.mesh, 0, 4); lovrMeshSetDrawRange(state.mesh, 0, 4);
lovrGraphicsDraw(state.mesh, NULL, SHADER_FILL, 1); lovrGraphicsDraw(state.mesh, SHADER_FILL, 1);
lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL); lovrMaterialSetTexture(material, TEXTURE_DIFFUSE, NULL);
lovrGraphicsSetDepthTest(mode, write); lovrGraphicsSetDepthTest(mode, write);
} }
// Internal // Internal
void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader defaultShader, int instances) { void lovrGraphicsDraw(Mesh* mesh, DefaultShader defaultShader, int instances) {
// Layer
Layer layer = state.layers[state.layer];
Canvas* canvas = state.canvasCount > 0 ? state.canvas[0] : layer.canvas;
gpuBindFramebuffer(canvas ? lovrCanvasGetId(canvas) : 0);
gpuSetViewport(state.canvasCount > 0 ?
(uint32_t[4]) { 0, 0, lovrTextureGetWidth((Texture*) state.canvas[0]), lovrTextureGetHeight((Texture*) state.canvas[0]) } :
layer.viewport
);
// Transforms
if (transform) {
lovrGraphicsPush();
lovrGraphicsMatrixTransform(transform);
}
Shader* shader = state.shader ? state.shader : state.defaultShaders[defaultShader]; Shader* shader = state.shader ? state.shader : state.defaultShaders[defaultShader];
if (!shader) { if (!shader) {
shader = state.defaultShaders[defaultShader] = lovrShaderCreateDefault(defaultShader); shader = state.defaultShaders[defaultShader] = lovrShaderCreateDefault(defaultShader);
} }
lovrShaderSetMatrix(shader, "lovrProjection", layer.projection, 16);
lovrShaderSetMatrix(shader, "lovrView", layer.view, 16);
mat4 model = state.transforms[state.transform];
lovrShaderSetMatrix(shader, "lovrModel", model, 16);
float modelView[16];
mat4_multiply(mat4_set(modelView, layer.view), model);
lovrShaderSetMatrix(shader, "lovrTransform", modelView, 16);
if (lovrShaderHasUniform(shader, "lovrNormalMatrix")) {
if (mat4_invert(modelView)) {
mat4_transpose(modelView);
} else {
mat4_identity(modelView);
}
float normalMatrix[9] = {
modelView[0], modelView[1], modelView[2],
modelView[4], modelView[5], modelView[6],
modelView[8], modelView[9], modelView[10],
};
lovrShaderSetMatrix(shader, "lovrNormalMatrix", normalMatrix, 9);
}
// 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 // Pose
float* pose = lovrMeshGetPose(mesh); float* pose = lovrMeshGetPose(mesh);
if (pose) { if (pose) {
@ -1076,51 +1011,59 @@ void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader defaultShader, i
// Material // Material
Material* material = lovrMeshGetMaterial(mesh); Material* material = lovrMeshGetMaterial(mesh);
material = material ? material : lovrGraphicsGetDefaultMaterial();
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);
}
gpuDraw(&(GpuDrawCommand) { gpuDraw(&(GpuDrawCommand) {
.mesh = mesh, .layer = state.layers[state.layer],
.shader = shader, .shader = shader,
.material = material,
.transform = state.transforms[state.transform],
.mesh = mesh,
.color = state.color,
.pointSize = state.pointSize,
.instances = instances .instances = instances
}); });
if (transform) {
lovrGraphicsPop();
}
} }
void lovrGraphicsPushLayer(Canvas* canvas) { void lovrGraphicsPushLayer(Canvas** canvas, int count, bool user) {
if (++state.layer >= MAX_LAYERS) { lovrAssert(count <= MAX_CANVASES, "Attempt to set %d canvases (the maximum is %d)", count, MAX_CANVASES);
lovrThrow("Layer overflow"); lovrAssert(++state.layer < MAX_LAYERS, "Layer overflow");
for (int i = 0; i < count; i++) {
lovrRetain(canvas[i]);
} }
memcpy(&state.layers[state.layer], &state.layers[state.layer - 1], sizeof(Layer)); Layer* prevLayer = &state.layers[state.layer - 1];
state.layers[state.layer].canvas = canvas; for (int i = 0; i < prevLayer->canvasCount; i++) {
lovrRelease(prevLayer->canvas[i]);
}
Layer* layer = &state.layers[state.layer];
memcpy(layer, prevLayer, sizeof(Layer));
layer->canvasCount = count;
layer->user = user;
if (count > 0) {
memcpy(layer->canvas, canvas, count * sizeof(Canvas*));
gpuBindFramebuffer(lovrCanvasGetId(canvas[0]));
GLenum buffers[MAX_CANVASES];
for (int i = 0; i < count; i++) {
buffers[i] = GL_COLOR_ATTACHMENT0 + i;
glFramebufferTexture2D(GL_FRAMEBUFFER, buffers[i], GL_TEXTURE_2D, lovrTextureGetId((Texture*) canvas[i]), 0);
}
glDrawBuffers(count, buffers);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
lovrAssert(status != GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "All multicanvas canvases must have the same dimensions");
lovrAssert(status == GL_FRAMEBUFFER_COMPLETE, "Unable to bind framebuffer");
}
} }
void lovrGraphicsPopLayer() { void lovrGraphicsPopLayer() {
if (state.canvasCount == 0 && state.layers[state.layer].canvas) { Layer* layer = &state.layers[state.layer];
lovrCanvasResolve(state.layers[state.layer].canvas); if (layer->canvasCount > 0) {
lovrCanvasResolve(layer->canvas[0]);
} }
lovrAssert(--state.layer >= 0, "Layer underflow"); lovrAssert(--state.layer >= 0, "Layer underflow");

View File

@ -12,7 +12,6 @@
#pragma once #pragma once
#define MAX_CANVASES 4
#define MAX_LAYERS 4 #define MAX_LAYERS 4
#define MAX_TRANSFORMS 60 #define MAX_TRANSFORMS 60
#define INTERNAL_TRANSFORMS 4 #define INTERNAL_TRANSFORMS 4
@ -72,13 +71,6 @@ typedef enum {
STENCIL_INVERT STENCIL_INVERT
} StencilAction; } StencilAction;
typedef struct {
float projection[16];
float view[16];
Canvas* canvas;
uint32_t viewport[4];
} Layer;
typedef struct { typedef struct {
bool initialized; bool initialized;
float pointSizes[2]; float pointSizes[2];
@ -100,8 +92,6 @@ typedef struct {
Color backgroundColor; Color backgroundColor;
BlendMode blendMode; BlendMode blendMode;
BlendAlphaMode blendAlphaMode; BlendAlphaMode blendAlphaMode;
Canvas* canvas[MAX_CANVASES];
int canvasCount;
Color color; Color color;
bool culling; bool culling;
TextureFilter defaultFilter; TextureFilter defaultFilter;
@ -191,9 +181,9 @@ void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback
void lovrGraphicsFill(Texture* texture); void lovrGraphicsFill(Texture* texture);
// Internal // Internal
void lovrGraphicsDraw(Mesh* mesh, mat4 transform, DefaultShader shader, int instances); void lovrGraphicsDraw(Mesh* mesh, DefaultShader shader, int instances);
VertexPointer lovrGraphicsGetVertexPointer(uint32_t capacity); VertexPointer lovrGraphicsGetVertexPointer(uint32_t capacity);
void lovrGraphicsPushLayer(Canvas* canvas); void lovrGraphicsPushLayer(Canvas** canvas, int count, bool user);
void lovrGraphicsPopLayer(); void lovrGraphicsPopLayer();
void lovrGraphicsSetCamera(mat4 projection, mat4 view); void lovrGraphicsSetCamera(mat4 projection, mat4 view);
void lovrGraphicsSetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height); void lovrGraphicsSetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height);

View File

@ -43,7 +43,7 @@ static void renderNode(Model* model, int nodeIndex, int instances) {
lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount); lovrMeshSetDrawRange(model->mesh, primitive->drawStart, primitive->drawCount);
lovrMeshSetPose(model->mesh, (float*) model->pose); lovrMeshSetPose(model->mesh, (float*) model->pose);
lovrGraphicsDraw(model->mesh, NULL, SHADER_DEFAULT, instances); lovrGraphicsDraw(model->mesh, SHADER_DEFAULT, instances);
} }
lovrGraphicsPop(); lovrGraphicsPop();

View File

@ -1,5 +1,7 @@
#include "graphics/gpu.h" #include "graphics/gpu.h"
#include "graphics/opengl/opengl.h" #include "graphics/opengl/opengl.h"
#include "resources/shaders.h"
#include "math/mat4.h"
#include "lib/glfw.h" #include "lib/glfw.h"
#include <string.h> #include <string.h>
@ -14,9 +16,18 @@ static struct {
uint32_t vertexArray; uint32_t vertexArray;
uint32_t vertexBuffer; uint32_t vertexBuffer;
uint32_t viewport[4]; uint32_t viewport[4];
bool srgb;
GpuStats stats; GpuStats stats;
} state; } state;
static void gammaCorrectColor(Color* color) {
if (state.srgb) {
color->r = lovrMathGammaToLinear(color->r);
color->g = lovrMathGammaToLinear(color->g);
color->b = lovrMathGammaToLinear(color->b);
}
}
void gpuInit(bool srgb, gpuProc (*getProcAddress)(const char*)) { void gpuInit(bool srgb, gpuProc (*getProcAddress)(const char*)) {
#ifndef EMSCRIPTEN #ifndef EMSCRIPTEN
gladLoadGLLoader((GLADloadproc) getProcAddress); gladLoadGLLoader((GLADloadproc) getProcAddress);
@ -31,6 +42,7 @@ void gpuInit(bool srgb, gpuProc (*getProcAddress)(const char*)) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
state.srgb = srgb;
} }
void gpuDestroy() { void gpuDestroy() {
@ -42,14 +54,74 @@ void gpuDestroy() {
void gpuDraw(GpuDrawCommand* command) { void gpuDraw(GpuDrawCommand* command) {
Mesh* mesh = command->mesh; Mesh* mesh = command->mesh;
Material* material = command->material;
Shader* shader = command->shader; Shader* shader = command->shader;
int instances = command->instances; int instances = command->instances;
// Transform
lovrShaderSetMatrix(shader, "lovrProjection", command->layer.projection, 16);
lovrShaderSetMatrix(shader, "lovrView", command->layer.view, 16);
lovrShaderSetMatrix(shader, "lovrModel", command->transform, 16);
float modelView[16];
mat4_multiply(mat4_set(modelView, command->layer.view), command->transform);
lovrShaderSetMatrix(shader, "lovrTransform", modelView, 16);
if (lovrShaderHasUniform(shader, "lovrNormalMatrix")) {
if (mat4_invert(modelView)) {
mat4_transpose(modelView);
} else {
mat4_identity(modelView);
}
float normalMatrix[9] = {
modelView[0], modelView[1], modelView[2],
modelView[4], modelView[5], modelView[6],
modelView[8], modelView[9], modelView[10],
};
lovrShaderSetMatrix(shader, "lovrNormalMatrix", normalMatrix, 9);
}
// Point size
lovrShaderSetFloat(shader, "lovrPointSize", &command->pointSize, 1);
// Color
Color color = command->color;
gammaCorrectColor(&color);
float data[4] = { color.r, color.g, color.b, color.a };
lovrShaderSetFloat(shader, "lovrColor", data, 4);
// Material
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);
}
// Layer
gpuBindFramebuffer(command->layer.canvasCount > 0 ? lovrCanvasGetId(command->layer.canvas[0]) : 0);
gpuSetViewport(command->layer.viewport);
// Shader
gpuUseProgram(lovrShaderGetProgram(shader)); gpuUseProgram(lovrShaderGetProgram(shader));
lovrShaderBind(shader); lovrShaderBind(shader);
// Attributes
lovrMeshBind(mesh, shader); lovrMeshBind(mesh, shader);
// TODEW // Draw (TODEW)
uint32_t rangeStart, rangeCount; uint32_t rangeStart, rangeCount;
lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount); lovrMeshGetDrawRange(mesh, &rangeStart, &rangeCount);
uint32_t indexCount; uint32_t indexCount;

View File

@ -292,7 +292,7 @@ static void fakeRenderTo(void (*callback)(void*), void* userdata) {
mat4_multiply(view, state.transform); mat4_multiply(view, state.transform);
mat4_invert(view); mat4_invert(view);
lovrGraphicsPushLayer(NULL); lovrGraphicsPushLayer(NULL, 0, false);
lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0); lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0);
lovrGraphicsSetCamera(projection, view); lovrGraphicsSetCamera(projection, view);
lovrGraphicsSetViewport(0, 0, width, height); lovrGraphicsSetViewport(0, 0, width, height);

View File

@ -671,7 +671,7 @@ static void openvrRenderTo(void (*callback)(void*), void* userdata) {
state.compositor->WaitGetPoses(state.renderPoses, 16, NULL, 0); state.compositor->WaitGetPoses(state.renderPoses, 16, NULL, 0);
mat4_fromMat34(head, state.renderPoses[state.headsetIndex].mDeviceToAbsoluteTracking.m); mat4_fromMat34(head, state.renderPoses[state.headsetIndex].mDeviceToAbsoluteTracking.m);
lovrGraphicsPushLayer(state.canvas); lovrGraphicsPushLayer(&state.canvas, 1, false);
lovrGraphicsClear(true, true, false, lovrGraphicsGetBackgroundColor(), 1., 0); lovrGraphicsClear(true, true, false, lovrGraphicsGetBackgroundColor(), 1., 0);
for (HeadsetEye i = EYE_LEFT; i <= EYE_RIGHT; i++) { for (HeadsetEye i = EYE_LEFT; i <= EYE_RIGHT; i++) {

View File

@ -89,7 +89,7 @@ static void onMountChanged(bool mounted) {
static void onFrame(float* leftView, float* rightView, float* leftProjection, float* rightProjection, void* userdata) { static void onFrame(float* leftView, float* rightView, float* leftProjection, float* rightProjection, void* userdata) {
int width, height; int width, height;
webvrGetDisplayDimensions(&width, &height); webvrGetDisplayDimensions(&width, &height);
lovrGraphicsPushLayer(NULL); lovrGraphicsPushLayer(NULL, 0, false);
lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0); lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0);
lovrGraphicsSetCamera(leftProjection, leftView); lovrGraphicsSetCamera(leftProjection, leftView);
lovrGraphicsSetViewport(0, 0, width, height); lovrGraphicsSetViewport(0, 0, width, height);