getCanvas; setCanvas; MRT; MULTICANVAS define;

This commit is contained in:
bjorn 2018-02-15 00:37:02 -08:00
parent 3287b0acb6
commit 7cecc1489e
10 changed files with 145 additions and 119 deletions

View File

@ -65,7 +65,6 @@ extern map_int_t ArcModes;
extern map_int_t AttributeTypes;
extern map_int_t BlendAlphaModes;
extern map_int_t BlendModes;
extern map_int_t CanvasTypes;
extern map_int_t CompareModes;
extern map_int_t ControllerAxes;
extern map_int_t ControllerButtons;

View File

@ -17,7 +17,6 @@ map_int_t ArcModes;
map_int_t AttributeTypes;
map_int_t BlendAlphaModes;
map_int_t BlendModes;
map_int_t CanvasTypes;
map_int_t CompareModes;
map_int_t DrawModes;
map_int_t FilterModes;
@ -130,10 +129,6 @@ int l_lovrGraphicsInit(lua_State* L) {
map_set(&BlendModes, "screen", BLEND_SCREEN);
map_set(&BlendModes, "replace", BLEND_REPLACE);
map_init(&CanvasTypes);
map_set(&CanvasTypes, "3d", CANVAS_3D);
map_set(&CanvasTypes, "2d", CANVAS_2D);
map_init(&CompareModes);
map_set(&CompareModes, "equal", COMPARE_EQUAL);
map_set(&CompareModes, "notequal", COMPARE_NOT_EQUAL);
@ -403,6 +398,26 @@ int l_lovrGraphicsSetBlendMode(lua_State* L) {
return 0;
}
int l_lovrGraphicsGetCanvas(lua_State* L) {
Canvas* canvas[MAX_CANVASES];
int count;
lovrGraphicsGetCanvas(canvas, &count);
for (int i = 0; i < count; i++) {
luax_pushtype(L, Canvas, canvas[i]);
}
return count;
}
int l_lovrGraphicsSetCanvas(lua_State* L) {
Canvas* canvas[MAX_CANVASES];
int count = MIN(lua_gettop(L), MAX_CANVASES);
for (int i = 0; i < count; i++) {
canvas[i] = luax_checktype(L, i + 1, Canvas);
}
lovrGraphicsSetCanvas(canvas, count);
return 0;
}
int l_lovrGraphicsGetColor(lua_State* L) {
Color color = lovrGraphicsGetColor();
lua_pushnumber(L, color.r);
@ -834,7 +849,6 @@ int l_lovrGraphicsNewCanvas(lua_State* L) {
luaL_argcheck(L, height > 0, 2, "height must be positive");
TextureFormat format = FORMAT_RGBA;
CanvasType type = CANVAS_3D;
int msaa = 0;
bool depth = true;
bool stencil = false;
@ -844,16 +858,12 @@ int l_lovrGraphicsNewCanvas(lua_State* L) {
format = *(TextureFormat*) luax_optenum(L, -1, "rgba", &TextureFormats, "canvas format");
lua_pop(L, 1);
lua_getfield(L, 3, "type");
type = *(CanvasType*) luax_optenum(L, -1, "3d", &CanvasTypes, "canvas type");
lua_pop(L, 1);
lua_getfield(L, 3, "msaa");
msaa = luaL_optinteger(L, -1, 0);
lua_pop(L, 1);
lua_getfield(L, 3, "depth");
depth = lua_isnil(L, -1) ? (type == CANVAS_3D) : lua_toboolean(L, -1);
depth = lua_toboolean(L, -1);
lua_pop(L, 1);
lua_getfield(L, 3, "stencil");
@ -865,7 +875,7 @@ int l_lovrGraphicsNewCanvas(lua_State* L) {
return luaL_error(L, "Unsupported texture format for canvas");
}
Canvas* canvas = lovrCanvasCreate(width, height, format, type, msaa, depth, stencil);
Canvas* canvas = lovrCanvasCreate(width, height, format, msaa, depth, stencil);
luax_pushtype(L, Canvas, canvas);
return 1;
}
@ -1097,6 +1107,8 @@ const luaL_Reg lovrGraphics[] = {
{ "setBackgroundColor", l_lovrGraphicsSetBackgroundColor },
{ "getBlendMode", l_lovrGraphicsGetBlendMode },
{ "setBlendMode", l_lovrGraphicsSetBlendMode },
{ "getCanvas", l_lovrGraphicsGetCanvas },
{ "setCanvas", l_lovrGraphicsSetCanvas },
{ "getColor", l_lovrGraphicsGetColor },
{ "setColor", l_lovrGraphicsSetColor },
{ "isCullingEnabled", l_lovrGraphicsIsCullingEnabled },

View File

@ -6,11 +6,13 @@ int l_lovrCanvasRenderTo(lua_State* L) {
Canvas* canvas = luax_checktype(L, 1, Canvas);
luaL_checktype(L, 2, LUA_TFUNCTION);
int nargs = lua_gettop(L) - 2;
lovrGraphicsPushView();
lovrCanvasBind(canvas);
Canvas* old[MAX_CANVASES];
int count;
lovrGraphicsGetCanvas(old, &count);
lovrGraphicsSetCanvas(&canvas, 1);
lua_call(L, nargs, 0);
lovrCanvasResolveMSAA(canvas);
lovrGraphicsPopView();
lovrGraphicsSetCanvas(old, count);
return 0;
}

View File

@ -19,14 +19,13 @@ bool lovrCanvasSupportsFormat(TextureFormat format) {
}
}
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasType type, int msaa, bool depth, bool stencil) {
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, int msaa, bool depth, bool stencil) {
TextureData* textureData = lovrTextureDataGetEmpty(width, height, format);
Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true);
if (!texture) return NULL;
Canvas* canvas = lovrAlloc(sizeof(Canvas), lovrCanvasDestroy);
canvas->texture = *texture;
canvas->type = type;
canvas->msaa = msaa;
canvas->framebuffer = 0;
canvas->resolveFramebuffer = 0;
@ -99,34 +98,6 @@ void lovrCanvasDestroy(const Ref* ref) {
lovrTextureDestroy(ref);
}
void lovrCanvasBind(Canvas* canvas) {
int width = canvas->texture.width;
int height = canvas->texture.height;
lovrGraphicsBindFramebuffer(canvas->framebuffer);
lovrGraphicsSetViewport(0, 0, width, height);
if (canvas->type == CANVAS_2D) {
float projection[16];
mat4_orthographic(projection, 0, width, 0, height, -1, 1);
lovrGraphicsSetProjection(projection);
}
}
void lovrCanvasResolveMSAA(Canvas* canvas) {
if (canvas->msaa == 0) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
return;
}
int width = canvas->texture.width;
int height = canvas->texture.height;
glBindFramebuffer(GL_READ_FRAMEBUFFER, canvas->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, canvas->resolveFramebuffer);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
TextureFormat lovrCanvasGetFormat(Canvas* canvas) {
return canvas->texture.slices[0]->format;
}

View File

@ -1,14 +1,10 @@
#include "graphics/texture.h"
#include "util.h"
typedef enum {
CANVAS_3D,
CANVAS_2D
} CanvasType;
#pragma once
typedef struct {
Texture texture;
CanvasType type;
GLuint framebuffer;
GLuint resolveFramebuffer;
GLuint depthStencilBuffer;
@ -18,9 +14,7 @@ typedef struct {
bool lovrCanvasSupportsFormat(TextureFormat format);
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, CanvasType type, int msaa, bool depth, bool stencil);
Canvas* lovrCanvasCreate(int width, int height, TextureFormat format, int msaa, bool depth, bool stencil);
void lovrCanvasDestroy(const Ref* ref);
void lovrCanvasBind(Canvas* canvas);
void lovrCanvasResolveMSAA(Canvas* canvas);
TextureFormat lovrCanvasGetFormat(Canvas* canvas);
int lovrCanvasGetMSAA(Canvas* canvas);

View File

@ -59,10 +59,14 @@ void lovrGraphicsDestroy() {
void lovrGraphicsReset() {
int w = lovrGraphicsGetWidth();
int h = lovrGraphicsGetHeight();
float projection[16];
state.transform = 0;
state.view = 0;
state.display = 0;
state.defaultShader = SHADER_DEFAULT;
mat4_perspective(state.displays[state.display].projection, .01f, 100.f, 67 * M_PI / 180., (float) w / h);
state.displays[state.display].viewport[0] = 0;
state.displays[state.display].viewport[1] = 0;
state.displays[state.display].viewport[2] = w;
state.displays[state.display].viewport[3] = h;
lovrGraphicsSetBackgroundColor((Color) { 0, 0, 0, 1. });
lovrGraphicsSetBlendMode(BLEND_ALPHA, BLEND_ALPHA_MULTIPLY);
lovrGraphicsSetColor((Color) { 1., 1., 1., 1. });
@ -77,7 +81,6 @@ void lovrGraphicsReset() {
lovrGraphicsSetWinding(WINDING_COUNTERCLOCKWISE);
lovrGraphicsSetWireframe(false);
lovrGraphicsSetViewport(0, 0, w, h);
lovrGraphicsSetProjection(mat4_perspective(projection, .01f, 100.f, 67 * M_PI / 180., (float) w / h));
lovrGraphicsOrigin();
}
@ -85,6 +88,9 @@ void lovrGraphicsClear(bool clearColor, bool clearDepth, bool clearStencil, Colo
if (clearColor) {
float c[4] = { color.r, color.g, color.b, color.a };
glClearBufferfv(GL_COLOR, 0, c);
for (int i = 1; i < state.canvasCount; i++) {
glClearBufferfv(GL_COLOR, i, c);
}
}
if (clearDepth) {
@ -111,7 +117,7 @@ void lovrGraphicsPrepare(Material* material, float* pose) {
mat4 model = state.transforms[state.transform][MATRIX_MODEL];
mat4 view = state.transforms[state.transform][MATRIX_VIEW];
mat4 projection = state.views[state.view].projection;
mat4 projection = state.displays[state.display].projection;
lovrShaderSetMatrix(shader, "lovrModel", model, 16);
lovrShaderSetMatrix(shader, "lovrView", view, 16);
lovrShaderSetMatrix(shader, "lovrProjection", projection, 16);
@ -338,6 +344,58 @@ void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode) {
}
}
void lovrGraphicsGetCanvas(Canvas** canvas, int* count) {
*count = state.canvasCount;
memcpy(canvas, state.canvas, state.canvasCount * sizeof(Canvas*));
}
void lovrGraphicsSetCanvas(Canvas** canvas, int count) {
if (count == state.canvasCount && !memcmp(state.canvas, canvas, count * sizeof(Canvas*))) {
return;
}
lovrAssert(count <= MAX_CANVASES, "Attempt to simultaneously render to %d canvases (the maximum is %d)", count, MAX_CANVASES);
if (state.canvasCount > 0 && state.canvas[0]->msaa > 0) {
int width = state.canvas[0]->texture.width;
int height = state.canvas[0]->texture.height;
glBindFramebuffer(GL_READ_FRAMEBUFFER, state.canvas[0]->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, state.canvas[0]->resolveFramebuffer);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
for (int i = 0; i < count; i++) {
lovrRetain(&canvas[i]->texture.ref);
}
for (int i = 0; i < state.canvasCount; i++) {
lovrRelease(&state.canvas[i]->texture.ref);
}
if (count == 0) {
lovrGraphicsBindFramebuffer(state.displays[state.display].framebuffer);
int* viewport = state.displays[state.display].viewport;
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
} else {
memcpy(state.canvas, canvas, count * sizeof(Canvas*));
lovrGraphicsBindFramebuffer(canvas[0]->framebuffer);
lovrGraphicsSetViewport(0, 0, canvas[0]->texture.width, canvas[0]->texture.height);
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, canvas[i]->texture.id, 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() {
return state.color;
}
@ -1133,42 +1191,33 @@ void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback
}
// Internal State
void lovrGraphicsPushView() {
if (++state.view >= MAX_VIEWS) {
lovrThrow("View overflow");
void lovrGraphicsPushDisplay(int framebuffer, mat4 projection, int* viewport) {
if (++state.display >= MAX_DISPLAYS) {
lovrThrow("Display overflow");
}
memcpy(&state.views[state.view], &state.views[state.view - 1], sizeof(View));
state.displays[state.display].framebuffer = framebuffer;
memcpy(state.displays[state.display].projection, projection, 16 * sizeof(float));
memcpy(state.displays[state.display].viewport, viewport, 4 * sizeof(int));
}
void lovrGraphicsPopView() {
if (--state.view < 0) {
lovrThrow("View underflow");
void lovrGraphicsPopDisplay() {
if (--state.display < 0) {
lovrThrow("Display underflow");
}
int* viewport = state.views[state.view].viewport;
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
lovrGraphicsBindFramebuffer(state.views[state.view].framebuffer);
}
mat4 lovrGraphicsGetProjection() {
return state.views[state.view].projection;
}
void lovrGraphicsSetProjection(mat4 projection) {
memcpy(state.views[state.view].projection, projection, 16 * sizeof(float));
if (state.canvasCount == 0) {
lovrGraphicsBindFramebuffer(state.displays[state.display].framebuffer);
int* viewport = state.displays[state.display].viewport;
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
void lovrGraphicsSetViewport(int x, int y, int w, int h) {
state.views[state.view].viewport[0] = x;
state.views[state.view].viewport[1] = y;
state.views[state.view].viewport[2] = w;
state.views[state.view].viewport[3] = h;
glViewport(x, y, w, h);
}
void lovrGraphicsBindFramebuffer(int framebuffer) {
state.views[state.view].framebuffer = framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
}

View File

@ -1,3 +1,4 @@
#include "graphics/canvas.h"
#include "graphics/font.h"
#include "graphics/material.h"
#include "graphics/mesh.h"
@ -9,7 +10,8 @@
#pragma once
#define MAX_VIEWS 4
#define MAX_CANVASES 4
#define MAX_DISPLAYS 4
#define MAX_TRANSFORMS 60
#define INTERNAL_TRANSFORMS 4
#define DEFAULT_SHADER_COUNT 4
@ -73,6 +75,12 @@ typedef enum {
MATRIX_VIEW
} MatrixType;
typedef struct {
int framebuffer;
float projection[16];
int viewport[4];
} Display;
typedef struct {
bool initialized;
float pointSizes[2];
@ -81,12 +89,6 @@ typedef struct {
float textureAnisotropy;
} GraphicsLimits;
typedef struct {
int framebuffer;
float projection[16];
int viewport[4];
} View;
typedef struct {
int drawCalls;
int shaderSwitches;
@ -104,6 +106,8 @@ typedef struct {
Color backgroundColor;
BlendMode blendMode;
BlendAlphaMode blendAlphaMode;
Canvas* canvas[MAX_CANVASES];
int canvasCount;
Color color;
bool culling;
TextureFilter defaultFilter;
@ -124,8 +128,8 @@ typedef struct {
uint32_t streamIBO;
vec_float_t streamData;
vec_uint_t streamIndices;
View views[MAX_VIEWS];
int view;
Display displays[MAX_DISPLAYS];
int display;
Texture* textures[MAX_TEXTURES];
bool stencilEnabled;
bool stencilWriting;
@ -153,6 +157,8 @@ Color lovrGraphicsGetBackgroundColor();
void lovrGraphicsSetBackgroundColor(Color color);
void lovrGraphicsGetBlendMode(BlendMode* mode, BlendAlphaMode* alphaMode);
void lovrGraphicsSetBlendMode(BlendMode mode, BlendAlphaMode alphaMode);
void lovrGraphicsGetCanvas(Canvas** canvas, int* count);
void lovrGraphicsSetCanvas(Canvas** canvas, int count);
Color lovrGraphicsGetColor();
void lovrGraphicsSetColor(Color color);
bool lovrGraphicsIsCullingEnabled();
@ -204,10 +210,8 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback callback, void* userdata);
// Internal State
void lovrGraphicsPushView();
void lovrGraphicsPopView();
mat4 lovrGraphicsGetProjection();
void lovrGraphicsSetProjection(mat4 projection);
void lovrGraphicsPushDisplay(int framebuffer, mat4 projection, int* viewport);
void lovrGraphicsPopDisplay();
void lovrGraphicsSetViewport(int x, int y, int w, int h);
void lovrGraphicsBindFramebuffer(int framebuffer);
Texture* lovrGraphicsGetTexture(int slot);

View File

@ -324,33 +324,27 @@ static ModelData* fakeControllerNewModelData(Controller* controller) {
}
static void fakeRenderTo(headsetRenderCallback callback, void* userdata) {
// float head[16], transform[16], projection[16];
// TODO: Head transform
// TODO: Eye transform
// Projection
int w,h;
GLFWwindow* window = glfwGetCurrentContext();
if(!window) {
return;
}
int w, h;
glfwGetWindowSize(window, &w, &h);
mat4_perspective(state.projection, state.clipNear, state.clipFar, 67 * M_PI / 180.0, (float) w / h);
mat4_perspective(state.projection, state.clipNear, state.clipFar, 67 * M_PI / 180.0, (float)w/h);
float transform[16];
mat4_set(transform, state.transform);
mat4_invert(transform);
// render
int viewport[4] = { 0, 0, w, h };
lovrGraphicsPushDisplay(0, state.projection, viewport);
lovrGraphicsPush();
float inv[16];
mat4_set(inv,state.transform);
mat4_invert(inv);
lovrGraphicsMatrixTransform(MATRIX_VIEW, inv);
lovrGraphicsSetProjection(state.projection);
lovrGraphicsMatrixTransform(MATRIX_VIEW, transform);
lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0);
callback(EYE_LEFT, userdata);
lovrGraphicsPop();
lovrGraphicsPopDisplay();
}
static void fakeUpdate(float dt) {

View File

@ -147,7 +147,7 @@ static void initializeCanvas() {
int msaa = 0;
glGetIntegerv(GL_SAMPLES, &msaa);
state.system->GetRecommendedRenderTargetSize(&state.renderWidth, &state.renderHeight);
state.canvas = lovrCanvasCreate(state.renderWidth, state.renderHeight, FORMAT_RGB, CANVAS_3D, msaa, true, true);
state.canvas = lovrCanvasCreate(state.renderWidth, state.renderHeight, FORMAT_RGB, msaa, true, true);
}
static void openvrInit() {
@ -733,8 +733,6 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
if (!state.isInitialized) return;
lovrGraphicsPushView();
if (!state.canvas) {
initializeCanvas();
}
@ -762,14 +760,14 @@ static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
mat4_fromMat44(projection, matrix);
// Render
lovrCanvasBind(state.canvas);
int viewport[4] = { 0, 0, state.canvas->texture.width, state.canvas->texture.height };
lovrGraphicsPushDisplay(state.canvas->texture.id, projection, viewport);
lovrGraphicsPush();
lovrGraphicsMatrixTransform(MATRIX_VIEW, transform);
lovrGraphicsSetProjection(projection);
lovrGraphicsClear(true, true, false, (Color) { 0, 0, 0, 0 }, 1., 0);
callback(eye, userdata);
lovrGraphicsPop();
lovrCanvasResolveMSAA(state.canvas);
lovrGraphicsPopDisplay();
// OpenVR changes the OpenGL texture binding, so we reset it after rendering
glActiveTexture(GL_TEXTURE0);
@ -788,7 +786,6 @@ static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
}
state.isRendering = false;
lovrGraphicsPopView();
if (state.isMirrored) {
Color oldColor = lovrGraphicsGetColor();

View File

@ -55,7 +55,7 @@ const char* lovrShaderFragmentPrefix = ""
#endif
"in vec2 texCoord; \n"
"in vec4 vertexColor; \n"
"out vec4 lovrFragColor; \n"
"out vec4 lovrCanvas[gl_MaxDrawBuffers]; \n"
"uniform float lovrMetalness; \n"
"uniform float lovrRoughness; \n"
"uniform vec4 lovrColor; \n"
@ -85,7 +85,11 @@ const char* lovrShaderVertexSuffix = ""
const char* lovrShaderFragmentSuffix = ""
"void main() { \n"
" lovrFragColor = color(lovrColor, lovrDiffuseTexture, texCoord); \n"
"#ifdef MULTICANVAS \n"
" colors(lovrColor, lovrDiffuseTexture, texCoord); \n"
"#else \n"
" lovrCanvas[0] = color(lovrColor, lovrDiffuseTexture, texCoord); \n"
"#endif \n"
"}";
const char* lovrDefaultVertexShader = ""