diff --git a/src/api/graphics.c b/src/api/graphics.c index 4f459efa..e763805e 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -1,6 +1,7 @@ #include "api/lovr.h" #include "graphics/graphics.h" #include "graphics/animator.h" +#include "graphics/canvas.h" #include "graphics/material.h" #include "graphics/mesh.h" #include "graphics/model.h" @@ -15,6 +16,7 @@ map_int_t ArcModes; map_int_t BlendAlphaModes; map_int_t BlendModes; +map_int_t CanvasTypes; map_int_t CompareModes; map_int_t DrawModes; map_int_t FilterModes; @@ -25,7 +27,6 @@ map_int_t MatrixTypes; map_int_t MeshAttributeTypes; map_int_t MeshDrawModes; map_int_t MeshUsages; -map_int_t TextureProjections; map_int_t VerticalAligns; map_int_t Windings; map_int_t WrapModes; @@ -82,6 +83,7 @@ int l_lovrGraphicsInit(lua_State* L) { luax_registertype(L, "Model", lovrModel); luax_registertype(L, "Shader", lovrShader); luax_registertype(L, "Texture", lovrTexture); + luax_extendtype(L, "Texture", "Canvas", lovrTexture, lovrCanvas); map_init(&ArcModes); map_set(&ArcModes, "pie", ARC_MODE_PIE); @@ -102,6 +104,10 @@ 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); @@ -154,10 +160,6 @@ int l_lovrGraphicsInit(lua_State* L) { map_set(&MeshUsages, "dynamic", MESH_DYNAMIC); map_set(&MeshUsages, "stream", MESH_STREAM); - map_init(&TextureProjections); - map_set(&TextureProjections, "2d", PROJECTION_ORTHOGRAPHIC); - map_set(&TextureProjections, "3d", PROJECTION_PERSPECTIVE); - map_init(&VerticalAligns); map_set(&VerticalAligns, "top", ALIGN_TOP); map_set(&VerticalAligns, "bottom", ALIGN_BOTTOM); @@ -696,6 +698,20 @@ int l_lovrGraphicsNewAnimator(lua_State* L) { return 1; } +int l_lovrGraphicsNewCanvas(lua_State* L) { + CanvasType type = CANVAS_3D; + int index = 1; + if (lua_type(L, index) == LUA_TSTRING) { + type = *(CanvasType*) luax_checkenum(L, index++, &CanvasTypes, "canvas type"); + } + int width = luaL_checkinteger(L, index++); + int height = luaL_checkinteger(L, index++); + int msaa = luaL_optinteger(L, index++, 0); + Canvas* canvas = lovrCanvasCreate(type, width, height, msaa); + luax_pushtype(L, Canvas, canvas); + return 1; +} + int l_lovrGraphicsNewFont(lua_State* L) { Blob* blob = NULL; float size; @@ -877,53 +893,42 @@ int l_lovrGraphicsNewShader(lua_State* L) { } int l_lovrGraphicsNewTexture(lua_State* L) { - Texture* texture; + Blob* blobs[6]; + bool isTable = lua_istable(L, 1); + int count = isTable ? lua_objlen(L, 1) : lua_gettop(L); - if (lua_type(L, 1) == LUA_TNUMBER) { - int width = luaL_checknumber(L, 1); - int height = luaL_checknumber(L, 2); - TextureProjection* projection = luax_optenum(L, 3, "3d", &TextureProjections, "projection"); - int msaa = luaL_optnumber(L, 4, 0); - TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA); - texture = lovrTextureCreateWithFramebuffer(textureData, *projection, msaa); - } else { - Blob* blobs[6]; - bool isTable = lua_istable(L, 1); - int count = isTable ? lua_objlen(L, 1) : lua_gettop(L); + if (count != 1 && count != 6) { + return luaL_error(L, "Expected 1 image for a 2D texture or 6 images for a cube texture, got %d", count); + } - if (count != 1 && count != 6) { - return luaL_error(L, "Expected 1 image for a 2D texture or 6 images for a cube texture, got %d", count); - } - - if (isTable) { - for (int i = 0; i < count; i++) { - lua_rawgeti(L, -1, i + 1); - blobs[i] = luax_readblob(L, -1, "Texture"); - lua_pop(L, 1); - } - } else { - for (int i = 0; i < count; i++) { - blobs[i] = luax_readblob(L, i + 1, "Texture"); - } - } - - bool srgb = true; - if (lua_istable(L, count + 1)) { - lua_getfield(L, count + 1, "linear"); - srgb = !lua_toboolean(L, -1); + if (isTable) { + for (int i = 0; i < count; i++) { + lua_rawgeti(L, -1, i + 1); + blobs[i] = luax_readblob(L, -1, "Texture"); lua_pop(L, 1); } - - TextureData* slices[6]; + } else { for (int i = 0; i < count; i++) { - slices[i] = lovrTextureDataFromBlob(blobs[i]); - lovrRelease(&blobs[i]->ref); + blobs[i] = luax_readblob(L, i + 1, "Texture"); } - - TextureType type = (count == 1) ? TEXTURE_2D : TEXTURE_CUBE; - texture = lovrTextureCreate(type, slices, count, srgb); } + bool srgb = true; + if (lua_istable(L, count + 1)) { + lua_getfield(L, count + 1, "linear"); + srgb = !lua_toboolean(L, -1); + lua_pop(L, 1); + } + + TextureData* slices[6]; + for (int i = 0; i < count; i++) { + slices[i] = lovrTextureDataFromBlob(blobs[i]); + lovrRelease(&blobs[i]->ref); + } + + TextureType type = (count == 1) ? TEXTURE_2D : TEXTURE_CUBE; + Texture* texture = lovrTextureCreate(type, slices, count, srgb); + luax_pushtype(L, Texture, texture); lovrRelease(&texture->ref); return 1; @@ -984,6 +989,7 @@ const luaL_Reg lovrGraphics[] = { { "skybox", l_lovrGraphicsSkybox }, { "print", l_lovrGraphicsPrint }, { "newAnimator", l_lovrGraphicsNewAnimator }, + { "newCanvas", l_lovrGraphicsNewCanvas }, { "newFont", l_lovrGraphicsNewFont }, { "newMaterial", l_lovrGraphicsNewMaterial }, { "newMesh", l_lovrGraphicsNewMesh }, diff --git a/src/api/lovr.h b/src/api/lovr.h index 5ccbe906..5cc8e727 100644 --- a/src/api/lovr.h +++ b/src/api/lovr.h @@ -19,6 +19,7 @@ extern const luaL_Reg lovrAnimator[]; extern const luaL_Reg lovrAudio[]; extern const luaL_Reg lovrBallJoint[]; extern const luaL_Reg lovrBoxShape[]; +extern const luaL_Reg lovrCanvas[]; extern const luaL_Reg lovrCapsuleShape[]; extern const luaL_Reg lovrController[]; extern const luaL_Reg lovrCylinderShape[]; @@ -50,6 +51,7 @@ extern const luaL_Reg lovrWorld[]; 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; @@ -70,7 +72,6 @@ extern map_int_t MeshDrawModes; extern map_int_t MeshUsages; extern map_int_t PolygonWindings; extern map_int_t ShapeTypes; -extern map_int_t TextureProjections; extern map_int_t TimeUnits; extern map_int_t VerticalAligns; extern map_int_t WrapModes; diff --git a/src/api/types/canvas.c b/src/api/types/canvas.c new file mode 100644 index 00000000..baa4a619 --- /dev/null +++ b/src/api/types/canvas.c @@ -0,0 +1,19 @@ +#include "api/lovr.h" +#include "graphics/graphics.h" +#include "graphics/canvas.h" + +int l_lovrCanvasRenderTo(lua_State* L) { + Canvas* canvas = luax_checktype(L, 1, Canvas); + lovrGraphicsPushView(); + lovrCanvasBind(canvas); + lua_settop(L, 2); + lua_call(L, 0, 0); + lovrCanvasResolveMSAA(canvas); + lovrGraphicsPopView(); + return 0; +} + +const luaL_Reg lovrCanvas[] = { + { "renderto", l_lovrCanvasRenderTo }, + { NULL, NULL } +}; diff --git a/src/api/types/texture.c b/src/api/types/texture.c index a05d2580..3143ff16 100644 --- a/src/api/types/texture.c +++ b/src/api/types/texture.c @@ -2,14 +2,14 @@ #include "graphics/graphics.h" int l_lovrTextureGetDimensions(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); lua_pushnumber(L, texture->width); lua_pushnumber(L, texture->height); return 2; } int l_lovrTextureGetFilter(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); TextureFilter filter = lovrTextureGetFilter(texture); luax_pushenum(L, &FilterModes, filter.mode); if (filter.mode == FILTER_ANISOTROPIC) { @@ -20,19 +20,19 @@ int l_lovrTextureGetFilter(lua_State* L) { } int l_lovrTextureGetHeight(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); lua_pushnumber(L, texture->height); return 1; } int l_lovrTextureGetWidth(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); lua_pushnumber(L, texture->width); return 1; } int l_lovrTextureGetWrap(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); TextureWrap wrap = lovrTextureGetWrap(texture); luax_pushenum(L, &WrapModes, wrap.s); luax_pushenum(L, &WrapModes, wrap.t); @@ -43,19 +43,8 @@ int l_lovrTextureGetWrap(lua_State* L) { return 2; } -int l_lovrTextureRenderTo(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); - lovrGraphicsPushView(); - lovrTextureBindFramebuffer(texture); - lua_settop(L, 2); - lua_call(L, 0, 0); - lovrTextureResolveMSAA(texture); - lovrGraphicsPopView(); - return 0; -} - int l_lovrTextureSetFilter(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); FilterMode mode = *(FilterMode*) luax_checkenum(L, 2, &FilterModes, "filter mode"); float anisotropy = luaL_optnumber(L, 3, 1.); TextureFilter filter = { .mode = mode, .anisotropy = anisotropy }; @@ -64,7 +53,7 @@ int l_lovrTextureSetFilter(lua_State* L) { } int l_lovrTextureSetWrap(lua_State* L) { - Texture* texture = luax_checktype(L, 1, Texture); + Texture* texture = luax_checktypeof(L, 1, Texture); TextureWrap wrap; wrap.s = *(WrapMode*) luax_checkenum(L, 2, &WrapModes, "wrap mode"); wrap.t = *(WrapMode*) luax_optenum(L, 3, luaL_checkstring(L, 2), &WrapModes, "wrap mode"); @@ -79,7 +68,6 @@ const luaL_Reg lovrTexture[] = { { "getHeight", l_lovrTextureGetHeight }, { "getWidth", l_lovrTextureGetWidth }, { "getWrap", l_lovrTextureGetWrap }, - { "renderTo", l_lovrTextureRenderTo }, { "setFilter", l_lovrTextureSetFilter }, { "setWrap", l_lovrTextureSetWrap }, { NULL, NULL } diff --git a/src/graphics/canvas.c b/src/graphics/canvas.c new file mode 100644 index 00000000..4a73e31e --- /dev/null +++ b/src/graphics/canvas.c @@ -0,0 +1,118 @@ +#include "graphics/canvas.h" +#include "graphics/graphics.h" +#include "math/mat4.h" +#include +#include + +Canvas* lovrCanvasCreate(CanvasType type, int width, int height, int msaa) { + TextureData* textureData = lovrTextureDataGetEmpty(width, height, FORMAT_RGBA); + 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; + canvas->depthBuffer = 0; + canvas->msaaTexture = 0; + + // Framebuffer + glGenFramebuffers(1, &canvas->framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, canvas->framebuffer); + + // Color attachment + if (msaa > 0) { + GLenum format = lovrGraphicsIsGammaCorrect() ? GL_SRGB8_ALPHA8 : GL_RGBA8; + glGenRenderbuffers(1, &canvas->msaaTexture); + glBindRenderbuffer(GL_RENDERBUFFER, canvas->msaaTexture); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, format, width, height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, canvas->msaaTexture); + } else { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas->texture.id, 0); + } + + // Depth attachment + if (type == CANVAS_3D) { + glGenRenderbuffers(1, &canvas->depthBuffer); + glBindRenderbuffer(GL_RENDERBUFFER, canvas->depthBuffer); + if (msaa > 0) { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT, width, height); + } else { + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); + } + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, canvas->depthBuffer); + } + + // Resolve framebuffer + if (msaa > 0) { + glGenFramebuffers(1, &canvas->resolveFramebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, canvas->resolveFramebuffer); + glBindTexture(GL_TEXTURE_2D, canvas->texture.id); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, canvas->texture.id, 0); + glBindFramebuffer(GL_FRAMEBUFFER, canvas->framebuffer); + } + + lovrAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Error creating texture"); + lovrGraphicsClear(true, true); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + return canvas; +} + +void lovrCanvasDestroy(const Ref* ref) { + Canvas* canvas = (Canvas*) containerof(ref, Texture); + glDeleteFramebuffers(1, &canvas->framebuffer); + if (canvas->resolveFramebuffer) { + glDeleteFramebuffers(1, &canvas->resolveFramebuffer); + } + if (canvas->depthBuffer) { + glDeleteRenderbuffers(1, &canvas->depthBuffer); + } + if (canvas->msaaTexture) { + glDeleteTextures(1, &canvas->msaaTexture); + } + 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); + } else { + mat4 projection = lovrGraphicsGetProjection(); + float b = projection[5]; + float c = projection[10]; + float d = projection[14]; + float aspect = (float) width / height; + float k = (c - 1.f) / (c + 1.f); + float near = (d * (1.f - k)) / (2.f * k); + float far = k * near; + float fov = -2.f * atan(1.f / b); + float newProjection[16]; + mat4_perspective(newProjection, near, far, fov, aspect); + lovrGraphicsSetProjection(newProjection); + } +} + +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); +} diff --git a/src/graphics/canvas.h b/src/graphics/canvas.h new file mode 100644 index 00000000..faab1328 --- /dev/null +++ b/src/graphics/canvas.h @@ -0,0 +1,22 @@ +#include "graphics/texture.h" +#include "util.h" + +typedef enum { + CANVAS_3D, + CANVAS_2D +} CanvasType; + +typedef struct { + Texture texture; + CanvasType type; + GLuint framebuffer; + GLuint resolveFramebuffer; + GLuint depthBuffer; + GLuint msaaTexture; + int msaa; +} Canvas; + +Canvas* lovrCanvasCreate(CanvasType, int width, int height, int msaa); +void lovrCanvasDestroy(const Ref* ref); +void lovrCanvasBind(Canvas* canvas); +void lovrCanvasResolveMSAA(Canvas* canvas); diff --git a/src/graphics/texture.c b/src/graphics/texture.c index 6b5b66fa..1e7a376d 100644 --- a/src/graphics/texture.c +++ b/src/graphics/texture.c @@ -1,7 +1,5 @@ #include "graphics/texture.h" #include "graphics/graphics.h" -#include "math/mat4.h" -#include #include #include @@ -96,8 +94,6 @@ Texture* lovrTextureCreate(TextureType type, TextureData* slices[6], int sliceCo validateSlices(type, slices, sliceCount); texture->sliceCount = sliceCount; memcpy(texture->slices, slices, sliceCount * sizeof(TextureData*)); - texture->framebuffer = 0; - texture->depthBuffer = 0; texture->srgb = srgb; glGenTextures(1, &texture->id); lovrGraphicsBindTexture(texture, type, 0); @@ -109,109 +105,15 @@ Texture* lovrTextureCreate(TextureType type, TextureData* slices[6], int sliceCo return texture; } -Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa) { - Texture* texture = lovrTextureCreate(TEXTURE_2D, &textureData, 1, true); - if (!texture) return NULL; - - int width = texture->width; - int height = texture->height; - texture->projection = projection; - texture->msaa = msaa; - - // Framebuffer - glGenFramebuffers(1, &texture->framebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, texture->framebuffer); - - // Color attachment - if (msaa) { - GLenum format = lovrGraphicsIsGammaCorrect() ? GL_SRGB8_ALPHA8 : GL_RGBA8; - glGenRenderbuffers(1, &texture->msaaId); - glBindRenderbuffer(GL_RENDERBUFFER, texture->msaaId); - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, format, width, height); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, texture->msaaId); - } else { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->id, 0); - } - - // Depth attachment - if (projection == PROJECTION_PERSPECTIVE) { - glGenRenderbuffers(1, &texture->depthBuffer); - glBindRenderbuffer(GL_RENDERBUFFER, texture->depthBuffer); - if (msaa) { - glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, GL_DEPTH_COMPONENT, width, height); - } else { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height); - } - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texture->depthBuffer); - } - - // Resolve framebuffer - if (msaa) { - glGenFramebuffers(1, &texture->resolveFramebuffer); - glBindFramebuffer(GL_FRAMEBUFFER, texture->resolveFramebuffer); - glBindTexture(GL_TEXTURE_2D, texture->id); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->id, 0); - glBindFramebuffer(GL_FRAMEBUFFER, texture->framebuffer); - } - - lovrAssert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Error creating texture"); - lovrGraphicsClear(true, true); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - return texture; -} - void lovrTextureDestroy(const Ref* ref) { Texture* texture = containerof(ref, Texture); for (int i = 0; i < texture->sliceCount; i++) { lovrTextureDataDestroy(texture->slices[i]); } - if (texture->framebuffer) { - glDeleteFramebuffers(1, &texture->framebuffer); - } glDeleteTextures(1, &texture->id); free(texture); } -void lovrTextureBindFramebuffer(Texture* texture) { - lovrAssert(texture->framebuffer, "Texture cannot be used as a canvas"); - lovrGraphicsBindFramebuffer(texture->framebuffer); - lovrGraphicsSetViewport(0, 0, texture->width, texture->height); - - if (texture->projection == PROJECTION_ORTHOGRAPHIC) { - float projection[16]; - mat4_orthographic(projection, 0, texture->width, 0, texture->height, -1, 1); - lovrGraphicsSetProjection(projection); - } else if (texture->projection == PROJECTION_PERSPECTIVE) { - mat4 projection = lovrGraphicsGetProjection(); - float b = projection[5]; - float c = projection[10]; - float d = projection[14]; - float aspect = (float) texture->width / texture->height; - float k = (c - 1.f) / (c + 1.f); - float near = (d * (1.f - k)) / (2.f * k); - float far = k * near; - float fov = -2.f * atan(1.f / b); - float newProjection[16]; - mat4_perspective(newProjection, near, far, fov, aspect); - lovrGraphicsSetProjection(newProjection); - } -} - -void lovrTextureResolveMSAA(Texture* texture) { - if (!texture->msaa) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - return; - } - - int width = texture->width; - int height = texture->height; - glBindFramebuffer(GL_READ_FRAMEBUFFER, texture->framebuffer); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, texture->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); -} - TextureFilter lovrTextureGetFilter(Texture* texture) { return texture->filter; } diff --git a/src/graphics/texture.h b/src/graphics/texture.h index 3c781cf3..eea33505 100644 --- a/src/graphics/texture.h +++ b/src/graphics/texture.h @@ -33,11 +33,6 @@ typedef struct { WrapMode r; } TextureWrap; -typedef enum { - PROJECTION_ORTHOGRAPHIC, - PROJECTION_PERSPECTIVE -} TextureProjection; - typedef struct { Ref ref; TextureType type; @@ -46,24 +41,15 @@ typedef struct { int width; int height; GLuint id; - GLuint msaaId; - GLuint framebuffer; - GLuint resolveFramebuffer; - GLuint depthBuffer; - TextureProjection projection; TextureFilter filter; TextureWrap wrap; - int msaa; bool srgb; } Texture; GLenum lovrTextureGetGLFormat(TextureFormat format); Texture* lovrTextureCreate(TextureType type, TextureData* data[6], int count, bool srgb); -Texture* lovrTextureCreateWithFramebuffer(TextureData* textureData, TextureProjection projection, int msaa); void lovrTextureDestroy(const Ref* ref); -void lovrTextureBindFramebuffer(Texture* texture); -void lovrTextureResolveMSAA(Texture* texture); TextureFilter lovrTextureGetFilter(Texture* texture); void lovrTextureSetFilter(Texture* texture, TextureFilter filter); TextureWrap lovrTextureGetWrap(Texture* texture); diff --git a/src/headset/openvr.c b/src/headset/openvr.c index bfb00496..b4042148 100644 --- a/src/headset/openvr.c +++ b/src/headset/openvr.c @@ -3,7 +3,7 @@ #include "math/mat4.h" #include "math/quat.h" #include "util.h" -#include "graphics/texture.h" +#include "graphics/canvas.h" #include #include #include @@ -51,12 +51,11 @@ typedef struct { float refreshRate; float vsyncToPhotons; - Texture* texture; + Canvas* canvas; } HeadsetState; static HeadsetState state; - static bool openvrIsAvailable() { if (VR_IsHmdPresent() && VR_IsRuntimeInstalled()) { return true; @@ -147,7 +146,7 @@ static void openvrInit() { state.isInitialized = false; state.isRendering = false; state.isMirrored = true; - state.texture = NULL; + state.canvas = NULL; vec_init(&state.controllers); for (int i = 0; i < 16; i++) { @@ -221,8 +220,8 @@ static void openvrInit() { static void openvrDestroy() { state.isInitialized = false; - if (state.texture) { - lovrRelease(&state.texture->ref); + if (state.canvas) { + lovrRelease(&state.canvas->texture.ref); } for (int i = 0; i < 16; i++) { if (state.deviceModels[i]) { @@ -737,10 +736,9 @@ static ModelData* openvrControllerNewModelData(Controller* controller) { static void openvrRenderTo(headsetRenderCallback callback, void* userdata) { if (!state.isInitialized) return; - if (!state.texture) { + if (!state.canvas) { state.system->GetRecommendedRenderTargetSize(&state.renderWidth, &state.renderHeight); - TextureData* textureData = lovrTextureDataGetEmpty(state.renderWidth, state.renderHeight, FORMAT_RGBA); - state.texture = lovrTextureCreateWithFramebuffer(textureData, PROJECTION_PERSPECTIVE, 4); + state.canvas = lovrCanvasCreate(CANVAS_3D, state.renderWidth, state.renderHeight, 4); } float head[16], transform[16], projection[16]; @@ -767,21 +765,21 @@ static void openvrRenderTo(headsetRenderCallback callback, void* userdata) { mat4_fromMat44(projection, matrix); // Render - lovrTextureBindFramebuffer(state.texture); + lovrCanvasBind(state.canvas); lovrGraphicsPush(); lovrGraphicsMatrixTransform(MATRIX_VIEW, transform); lovrGraphicsSetProjection(projection); lovrGraphicsClear(true, true); callback(eye, userdata); lovrGraphicsPop(); - lovrTextureResolveMSAA(state.texture); + lovrCanvasResolveMSAA(state.canvas); // 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.texture->id; + 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 }; @@ -805,7 +803,7 @@ static void openvrRenderTo(headsetRenderCallback callback, void* userdata) { } lovrGraphicsSetShader(NULL); - lovrGraphicsPlaneFullscreen(state.texture); + lovrGraphicsPlaneFullscreen(&state.canvas->texture); lovrGraphicsSetShader(lastShader); if (lastShader) {