diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index b437ecef..85a0d7d3 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -17,9 +17,10 @@ void lovrGraphicsInit() { for (int i = 0; i < MAX_TRANSFORMS; i++) { state.transforms[i] = mat4_init(); } - state.canvases[0].framebuffer = 0; - glGetIntegerv(GL_VIEWPORT, state.canvases[0].viewport); - state.canvases[0].isSystem = 1; + for (int i = 0; i < MAX_CANVASES; i++) { + state.canvases[i] = malloc(sizeof(CanvasState)); + state.canvases[i]->projection = mat4_init(); + } state.defaultShader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader); state.skyboxShader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader); int uniformId = lovrShaderGetUniformId(state.skyboxShader, "cube"); @@ -40,6 +41,10 @@ void lovrGraphicsDestroy() { for (int i = 0; i < MAX_TRANSFORMS; i++) { mat4_deinit(state.transforms[i]); } + for (int i = 0; i < MAX_CANVASES; i++) { + mat4_deinit(state.canvases[i]->projection); + free(state.canvases[i]); + } lovrRelease(&state.defaultShader->ref); lovrRelease(&state.skyboxShader->ref); lovrRelease(&state.defaultTexture->ref); @@ -53,7 +58,9 @@ void lovrGraphicsDestroy() { void lovrGraphicsReset() { state.transform = 0; state.canvas = 0; + lovrGraphicsSetViewport(0, 0, lovrGraphicsGetWidth(), lovrGraphicsGetHeight()); lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180); // TODO customize via lovr.conf + lovrGraphicsBindFramebuffer(0); lovrGraphicsSetShader(NULL); lovrGraphicsBindTexture(NULL); lovrGraphicsSetBackgroundColor(0, 0, 0, 0); @@ -89,7 +96,7 @@ void lovrGraphicsPresent() { void lovrGraphicsPrepare() { Shader* shader = lovrGraphicsGetShader(); mat4 transform = state.transforms[state.transform]; - mat4 projection = state.canvases[state.canvas].projection; + mat4 projection = state.canvases[state.canvas]->projection; lovrShaderBind(shader, transform, projection, state.color, 0); } @@ -192,7 +199,11 @@ void lovrGraphicsBindTexture(Texture* texture) { void lovrGraphicsSetProjection(float near, float far, float fov) { int width, height; glfwGetWindowSize(window, &width, &height); - mat4_setProjection(state.canvases[state.canvas].projection, near, far, fov, (float) width / height); + mat4_setProjection(state.canvases[state.canvas]->projection, near, far, fov, (float) width / height); +} + +void lovrGraphicsSetProjectionRaw(mat4 projection) { + memcpy(state.canvases[state.canvas]->projection, projection, 16 * sizeof(float)); } float lovrGraphicsGetLineWidth() { @@ -274,17 +285,12 @@ int lovrGraphicsGetHeight() { return height; } -void lovrGraphicsPushCanvas(CanvasState canvasState) { - if (!canvasState.isSystem && !state.canvases[state.canvas].isSystem) { - lovrGraphicsPopCanvas(); - } else if (++state.canvas >= MAX_CANVASES) { +void lovrGraphicsPushCanvas() { + if (++state.canvas >= MAX_CANVASES) { error("Canvas overflow"); } - int* viewport = canvasState.viewport; - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glBindFramebuffer(GL_FRAMEBUFFER, canvasState.framebuffer); - state.canvases[state.canvas] = canvasState; + memcpy(state.canvases[state.canvas], state.canvases[state.canvas - 1], sizeof(CanvasState)); } void lovrGraphicsPopCanvas() { @@ -292,10 +298,22 @@ void lovrGraphicsPopCanvas() { error("Canvas underflow"); } - CanvasState* canvasState = &state.canvases[state.canvas]; - int* viewport = canvasState->viewport; - glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glBindFramebuffer(GL_FRAMEBUFFER, canvasState->framebuffer); + int* viewport = state.canvases[state.canvas]->viewport; + lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + lovrGraphicsBindFramebuffer(state.canvases[state.canvas]->framebuffer); +} + +void lovrGraphicsSetViewport(int x, int y, int w, int h) { + state.canvases[state.canvas]->viewport[0] = x; + state.canvases[state.canvas]->viewport[1] = y; + state.canvases[state.canvas]->viewport[2] = w; + state.canvases[state.canvas]->viewport[3] = h; + glViewport(x, y, w, h); +} + +void lovrGraphicsBindFramebuffer(int framebuffer) { + state.canvases[state.canvas]->framebuffer = framebuffer; + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); } // Transforms diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index 6cf25833..b5d59f8b 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -40,9 +40,8 @@ typedef struct { typedef struct CanvasState { int framebuffer; - float projection[16]; + mat4 projection; int viewport[4]; - int isSystem; } CanvasState; typedef struct { @@ -53,7 +52,7 @@ typedef struct { int transform; mat4 transforms[MAX_TRANSFORMS]; int canvas; - CanvasState canvases[MAX_CANVASES]; + CanvasState* canvases[MAX_CANVASES]; unsigned int color; char colorMask; int isScissorEnabled; @@ -96,6 +95,7 @@ Shader* lovrGraphicsGetShader(); void lovrGraphicsSetShader(Shader* shader); void lovrGraphicsBindTexture(Texture* texture); void lovrGraphicsSetProjection(float near, float far, float fov); +void lovrGraphicsSetProjectionRaw(mat4 projection); float lovrGraphicsGetLineWidth(); void lovrGraphicsSetLineWidth(float width); float lovrGraphicsGetPointSize(); @@ -110,8 +110,10 @@ int lovrGraphicsIsWireframe(); void lovrGraphicsSetWireframe(int wireframe); int lovrGraphicsGetWidth(); int lovrGraphicsGetHeight(); -void lovrGraphicsPushCanvas(CanvasState canvasState); +void lovrGraphicsPushCanvas(); void lovrGraphicsPopCanvas(); +void lovrGraphicsSetViewport(int x, int y, int w, int h); +void lovrGraphicsBindFramebuffer(int framebuffer); // Transforms int lovrGraphicsPush(); diff --git a/src/graphics/texture.c b/src/graphics/texture.c index 3d5d7aae..b0ae2904 100644 --- a/src/graphics/texture.c +++ b/src/graphics/texture.c @@ -48,20 +48,16 @@ void lovrTextureBind(Texture* texture) { glBindTexture(GL_TEXTURE_2D, texture->id); } -CanvasState lovrTextureGetCanvasState(Texture* texture) { +void lovrTextureBindFramebuffer(Texture* texture) { if (!texture->fbo) { error("Texture cannot be used as a canvas"); } - CanvasState canvasState = { - .framebuffer = texture->fbo, - .viewport = { 0, 0, texture->textureData->width, texture->textureData->height }, - .isSystem = 0 - }; - - mat4_setIdentity(canvasState.projection); // TODO - - return canvasState; + lovrGraphicsBindFramebuffer(texture->fbo); + lovrGraphicsSetViewport(0, 0, texture->textureData->width, texture->textureData->height); + if (0) { + // lovrGraphicsSetProjection(); // TODO ortho + } } int lovrTextureGetHeight(Texture* texture) { diff --git a/src/graphics/texture.h b/src/graphics/texture.h index 71722d89..7c86ff41 100644 --- a/src/graphics/texture.h +++ b/src/graphics/texture.h @@ -42,7 +42,7 @@ Texture* lovrTextureCreate(TextureData* textureData, int hasFramebuffer); void lovrTextureDestroy(const Ref* ref); void lovrTextureDataDestroy(TextureData* textureData); void lovrTextureBind(Texture* texture); -struct CanvasState lovrTextureGetCanvasState(Texture* texture); +void lovrTextureBindFramebuffer(Texture* texture); void lovrTextureRefresh(Texture* texture); int lovrTextureGetHeight(Texture* texture); int lovrTextureGetWidth(Texture* texture); diff --git a/src/headset/vive.c b/src/headset/vive.c index a72de634..35136a64 100644 --- a/src/headset/vive.c +++ b/src/headset/vive.c @@ -484,50 +484,53 @@ void* viveControllerGetModel(void* headset, Controller* controller, ControllerMo void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata) { Vive* vive = (Vive*) headset; - CanvasState canvasState = { - .framebuffer = vive->framebuffer, - .viewport = { 0, 0, vive->renderWidth, vive->renderHeight }, - .isSystem = 1 - }; - float headMatrix[16], eyeMatrix[16]; + float projectionMatrix[16], headMatrix[16], eyeMatrix[16]; float (*matrix)[4]; + float near = vive->clipNear; + float far = vive->clipFar; + lovrGraphicsPushCanvas(); + lovrGraphicsSetViewport(0, 0, vive->renderWidth, vive->renderHeight); vive->isRendering = 1; vive->compositor->WaitGetPoses(vive->renderPoses, 16, NULL, 0); + + // Head transform matrix = vive->renderPoses[vive->headsetIndex].mDeviceToAbsoluteTracking.m; mat4_invert(mat4_fromMat34(headMatrix, matrix)); for (int i = 0; i < 2; i++) { EVREye eye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right; + // Eye transform matrix = vive->system->GetEyeToHeadTransform(eye).m; mat4_invert(mat4_fromMat34(eyeMatrix, matrix)); mat4 transformMatrix = mat4_multiply(eyeMatrix, headMatrix); - float near = vive->clipNear; - float far = vive->clipFar; + // Projection matrix = vive->system->GetProjectionMatrix(eye, near, far).m; - mat4_fromMat44(canvasState.projection, matrix); + mat4_fromMat44(projectionMatrix, matrix); + // Render glEnable(GL_MULTISAMPLE); - - lovrGraphicsPushCanvas(canvasState); + lovrGraphicsBindFramebuffer(vive->framebuffer); lovrGraphicsClear(1, 1); lovrGraphicsPush(); lovrGraphicsOrigin(); lovrGraphicsMatrixTransform(transformMatrix); + lovrGraphicsSetProjectionRaw(projectionMatrix); callback(i, userdata); lovrGraphicsPop(); - lovrGraphicsPopCanvas(); - + lovrGraphicsBindFramebuffer(0); glDisable(GL_MULTISAMPLE); + // Blit glBindFramebuffer(GL_READ_FRAMEBUFFER, vive->framebuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, vive->resolveFramebuffer); glBlitFramebuffer(0, 0, vive->renderWidth, vive->renderHeight, 0, 0, vive->renderWidth, vive->renderHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + // Submit uintptr_t texture = (uintptr_t) vive->resolveTexture; ETextureType textureType = ETextureType_TextureType_OpenGL; Texture_t eyeTexture = { (void*) texture, textureType, EColorSpace_ColorSpace_Gamma }; @@ -536,4 +539,5 @@ void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata) } vive->isRendering = 0; + lovrGraphicsPopCanvas(); } diff --git a/src/lovr/types/texture.c b/src/lovr/types/texture.c index 525e9989..df2caa08 100644 --- a/src/lovr/types/texture.c +++ b/src/lovr/types/texture.c @@ -61,7 +61,8 @@ int l_lovrTextureGetWrap(lua_State* L) { int l_lovrTextureRenderTo(lua_State* L) { Texture* texture = luax_checktype(L, 1, Texture); - lovrGraphicsPushCanvas(lovrTextureGetCanvasState(texture)); + lovrGraphicsPushCanvas(); + lovrTextureBindFramebuffer(texture); lua_settop(L, 2); lua_call(L, 0, 0); lovrGraphicsPopCanvas();