Refactor layers/displays;

This commit is contained in:
bjorn 2018-03-04 21:51:53 -08:00
parent 221015677f
commit 2def650abd
4 changed files with 84 additions and 90 deletions

View File

@ -58,14 +58,14 @@ void lovrGraphicsReset() {
int w = lovrGraphicsGetWidth();
int h = lovrGraphicsGetHeight();
state.transform = 0;
state.display = 0;
state.layer = 0;
state.defaultShader = SHADER_DEFAULT;
mat4_perspective(state.displays[state.display].projections, .01f, 100.f, 67 * M_PI / 180., (float) w / h / 2.);
mat4_perspective(state.displays[state.display].projections + 16, .01f, 100.f, 67 * M_PI / 180., (float) w / h / 2.);
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;
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.);
state.layers[state.layer].viewport[0] = 0;
state.layers[state.layer].viewport[1] = 0;
state.layers[state.layer].viewport[2] = w;
state.layers[state.layer].viewport[3] = h;
lovrGraphicsSetBackgroundColor((Color) { 0, 0, 0, 1. });
lovrGraphicsSetBlendMode(BLEND_ALPHA, BLEND_ALPHA_MULTIPLY);
lovrGraphicsSetColor((Color) { 1., 1., 1., 1. });
@ -118,7 +118,7 @@ void lovrGraphicsPrepare(Material* material, float* pose) {
mat4 model = state.transforms[state.transform][MATRIX_MODEL];
lovrShaderSetMatrix(shader, "lovrModel", model, 16);
float* views = state.displays[state.display].views;
float* views = state.layers[state.layer].views;
float transforms[32];
mat4_multiply(mat4_set(transforms + 0, views + 0), model);
mat4_multiply(mat4_set(transforms + 16, views + 16), model);
@ -371,8 +371,9 @@ void lovrGraphicsSetCanvas(Canvas** canvas, int count) {
}
if (count == 0) {
lovrGraphicsBindFramebuffer(state.displays[state.display].framebuffer);
int* viewport = state.displays[state.display].viewport;
Layer layer = state.layers[state.layer];
int* viewport = layer.viewport;
lovrGraphicsBindFramebuffer(layer.canvas ? layer.canvas->texture.id : 0);
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
} else {
memcpy(state.canvas, canvas, count * sizeof(Canvas*));
@ -1143,41 +1144,32 @@ void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback
}
// Internal State
void lovrGraphicsPushDisplay(int framebuffer, float* projections, float* views, int* viewport) {
if (++state.display >= MAX_DISPLAYS) {
lovrThrow("Display overflow");
void lovrGraphicsPushLayer(Layer layer) {
if (++state.layer >= MAX_LAYERS) {
lovrThrow("Layer overflow");
}
state.displays[state.display].framebuffer = framebuffer;
memcpy(state.displays[state.display].projections, projections, 32 * sizeof(float));
memcpy(state.displays[state.display].views, views, 32 * sizeof(float));
memcpy(state.displays[state.display].viewport, viewport, 4 * sizeof(int));
struct {
float projections[32];
float views[32];
} cameraBlock;
memcpy(cameraBlock.projections, projections, 32 * sizeof(float));
memcpy(cameraBlock.views, views, 32 * sizeof(float));
memcpy(&state.layers[state.layer], &layer, sizeof(Layer));
glBindBuffer(GL_UNIFORM_BUFFER, state.cameraUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 16 * sizeof(float), &cameraBlock);
glBufferSubData(GL_UNIFORM_BUFFER, 0, 4 * 16 * sizeof(float), &layer);
if (state.canvasCount == 0) {
lovrGraphicsBindFramebuffer(framebuffer);
int* viewport = layer.viewport;
lovrGraphicsBindFramebuffer(layer.canvas ? layer.canvas->texture.id : 0);
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}
void lovrGraphicsPopDisplay() {
if (--state.display < 0) {
lovrThrow("Display underflow");
void lovrGraphicsPopLayer() {
if (--state.layer < 0) {
lovrThrow("Layer underflow");
}
if (state.canvasCount == 0) {
lovrGraphicsBindFramebuffer(state.displays[state.display].framebuffer);
int* viewport = state.displays[state.display].viewport;
Layer layer = state.layers[state.layer];
int* viewport = layer.viewport;
lovrGraphicsBindFramebuffer(layer.canvas ? layer.canvas->texture.id : 0);
lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
}

View File

@ -11,7 +11,7 @@
#pragma once
#define MAX_CANVASES 4
#define MAX_DISPLAYS 4
#define MAX_LAYERS 4
#define MAX_TRANSFORMS 60
#define INTERNAL_TRANSFORMS 4
#define DEFAULT_SHADER_COUNT 4
@ -76,11 +76,11 @@ typedef enum {
} MatrixType;
typedef struct {
int framebuffer;
float projections[32];
float views[32];
Canvas* canvas;
int viewport[4];
} Display;
} Layer;
typedef struct {
bool initialized;
@ -127,8 +127,8 @@ typedef struct {
bool wireframe;
Mesh* mesh;
uint32_t cameraUBO;
Display displays[MAX_DISPLAYS];
int display;
Layer layers[MAX_LAYERS];
int layer;
Texture* textures[MAX_TEXTURES];
bool stencilEnabled;
bool stencilWriting;
@ -210,8 +210,8 @@ void lovrGraphicsStencil(StencilAction action, int replaceValue, StencilCallback
// Internal State
VertexPointer lovrGraphicsGetVertexPointer(uint32_t capacity);
void lovrGraphicsPushDisplay(int framebuffer, float* projections, float* views, int* viewport);
void lovrGraphicsPopDisplay();
void lovrGraphicsPushLayer(Layer layer);
void lovrGraphicsPopLayer();
void lovrGraphicsSetViewport(int x, int y, int w, int h);
void lovrGraphicsBindFramebuffer(int framebuffer);
Texture* lovrGraphicsGetTexture(int slot);

View File

@ -313,22 +313,21 @@ static void fakeRenderTo(headsetRenderCallback callback, void* userdata) {
int width, height;
fakeGetDisplayDimensions(&width, &height);
float projections[32];
mat4_perspective(projections, state.clipNear, state.clipFar, 67 * M_PI / 180., (float) width / height / 2.);
mat4_set(projections + 16, projections);
Layer layer = { .canvas = NULL, .viewport = { 0, 0, width, height } };
float views[32];
mat4_identity(views);
mat4_translate(views, 0, state.offset, 0);
mat4_multiply(views, state.transform);
mat4_invert(views);
mat4_set(views + 16, views);
mat4_perspective(layer.projections, state.clipNear, state.clipFar, 67 * M_PI / 180., (float) width / height / 2.);
mat4_set(layer.projections + 16, layer.projections);
int viewport[4] = { 0, 0, width, height };
lovrGraphicsPushDisplay(0, projections, views, viewport);
mat4_identity(layer.views);
mat4_translate(layer.views, 0, state.offset, 0);
mat4_multiply(layer.views, state.transform);
mat4_invert(layer.views);
mat4_set(layer.views + 16, layer.views);
lovrGraphicsPushLayer(layer);
lovrGraphicsClear(true, true, true, lovrGraphicsGetBackgroundColor(), 1., 0);
callback(EYE_LEFT, userdata);
lovrGraphicsPopDisplay();
lovrGraphicsPopLayer();
}
static void fakeUpdate(float dt) {

View File

@ -247,7 +247,7 @@ static void ensureCanvas() {
int msaa = 0;
glGetIntegerv(GL_SAMPLES, &msaa);
state.system->GetRecommendedRenderTargetSize(&state.renderWidth, &state.renderHeight);
state.canvas = lovrCanvasCreate(state.renderWidth, state.renderHeight, FORMAT_RGB, msaa, true, true);
state.canvas = lovrCanvasCreate(state.renderWidth * 2, state.renderHeight, FORMAT_RGB, msaa, true, true);
}
static bool openvrInit(float offset) {
@ -311,7 +311,7 @@ static bool openvrInit(float offset) {
state.vsyncToPhotons = state.system->GetFloatTrackedDeviceProperty(state.headsetIndex, ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float, NULL);
state.isRendering = false;
state.isMirrored = true;
state.offset = offset;
state.offset = lovrHeadsetGetOriginType() == ORIGIN_HEAD ? offset : 0.;
state.canvas = NULL;
state.clipNear = 0.1f;
state.clipFar = 30.f;
@ -672,55 +672,58 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
static void openvrRenderTo(headsetRenderCallback callback, void* userdata) {
ensureCanvas();
float head[16], transform[16], projection[16];
float (*matrix)[4];
state.isRendering = true;
state.compositor->WaitGetPoses(state.renderPoses, 16, NULL, 0);
// Head transform
// Layer setup
Layer layer = { .canvas = state.canvas, .viewport = { 0, 0, state.renderWidth * 2, state.renderHeight } };
float eye[16];
float head[16];
float (*matrix)[4];
matrix = state.renderPoses[state.headsetIndex].mDeviceToAbsoluteTracking.m;
mat4_invert(mat4_fromMat34(head, matrix));
mat4_fromMat34(head, matrix);
for (HeadsetEye eye = EYE_LEFT; eye <= EYE_RIGHT; eye++) {
// Eye transform
EVREye vrEye = (eye == EYE_LEFT) ? EVREye_Eye_Left : EVREye_Eye_Right;
matrix = state.system->GetEyeToHeadTransform(vrEye).m;
mat4_invert(mat4_fromMat34(transform, matrix));
mat4_multiply(transform, head);
for (HeadsetEye i = EYE_LEFT; i <= EYE_RIGHT; i++) {
EVREye vrEye = (i == EYE_LEFT) ? EVREye_Eye_Left : EVREye_Eye_Right;
// Projection
matrix = state.system->GetProjectionMatrix(vrEye, state.clipNear, state.clipFar).m;
mat4 projection = layer.projections + 16 * i;
mat4_fromMat44(projection, matrix);
// Render
//int viewport[4] = { 0, 0, state.canvas->texture.width, state.canvas->texture.height };
//lovrGraphicsPushDisplay(state.canvas->framebuffer, projection, viewport);
lovrGraphicsPush();
lovrGraphicsMatrixTransform(MATRIX_VIEW, transform);
lovrGraphicsClear(true, true, false, lovrGraphicsGetBackgroundColor(), 1., 0);
callback(eye, userdata);
lovrGraphicsPop();
//lovrGraphicsPopDisplay();
// OpenVR changes the OpenGL texture binding, so we reset it after rendering
glActiveTexture(GL_TEXTURE0);
Texture* oldTexture = lovrGraphicsGetTexture(0);
// Submit
uintptr_t texture = (uintptr_t) state.canvas->texture.id;
ETextureType textureType = ETextureType_TextureType_OpenGL;
EColorSpace colorSpace = lovrGraphicsIsGammaCorrect() ? EColorSpace_ColorSpace_Linear : EColorSpace_ColorSpace_Gamma;
Texture_t eyeTexture = { (void*) texture, textureType, colorSpace };
EVRSubmitFlags flags = EVRSubmitFlags_Submit_Default;
state.compositor->Submit(vrEye, &eyeTexture, NULL, flags);
// Reset to the correct texture
glBindTexture(GL_TEXTURE_2D, oldTexture->id);
// View
matrix = state.system->GetEyeToHeadTransform(vrEye).m;
mat4_fromMat34(eye, matrix);
mat4 view = layer.views + 16 * i;
mat4_identity(view);
mat4_translate(view, 0, state.offset, 0);
mat4_multiply(view, head);
mat4_multiply(view, eye);
mat4_invert(view);
}
// Render
lovrGraphicsPushLayer(layer);
lovrGraphicsClear(true, true, false, lovrGraphicsGetBackgroundColor(), 1., 0);
callback(EYE_LEFT, userdata);
lovrGraphicsPopLayer();
// OpenVR changes the OpenGL texture binding, so we reset it after rendering
glActiveTexture(GL_TEXTURE0);
Texture* oldTexture = lovrGraphicsGetTexture(0);
// Submit
uintptr_t texture = (uintptr_t) state.canvas->texture.id;
EColorSpace colorSpace = lovrGraphicsIsGammaCorrect() ? EColorSpace_ColorSpace_Linear : EColorSpace_ColorSpace_Gamma;
Texture_t eyeTexture = { (void*) texture, ETextureType_TextureType_OpenGL, colorSpace };
VRTextureBounds_t left = { 0, 0, state.renderWidth, state.renderHeight };
VRTextureBounds_t right = { state.renderWidth, 0, state.renderWidth, state.renderHeight };
state.compositor->Submit(EVREye_Eye_Left, &eyeTexture, &left, EVRSubmitFlags_Submit_Default);
state.compositor->Submit(EVREye_Eye_Right, &eyeTexture, &right, EVRSubmitFlags_Submit_Default);
// Reset to the correct texture
glBindTexture(GL_TEXTURE_2D, oldTexture->id);
state.isRendering = false;
if (state.isMirrored) {