mirror of https://github.com/bjornbytes/lovr.git
Start Canvas objects;
This commit is contained in:
parent
8eec247adb
commit
d261e4b00d
|
@ -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,16 +893,6 @@ int l_lovrGraphicsNewShader(lua_State* L) {
|
|||
}
|
||||
|
||||
int l_lovrGraphicsNewTexture(lua_State* L) {
|
||||
Texture* texture;
|
||||
|
||||
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);
|
||||
|
@ -921,8 +927,7 @@ int l_lovrGraphicsNewTexture(lua_State* L) {
|
|||
}
|
||||
|
||||
TextureType type = (count == 1) ? TEXTURE_2D : TEXTURE_CUBE;
|
||||
texture = lovrTextureCreate(type, slices, count, srgb);
|
||||
}
|
||||
Texture* texture = lovrTextureCreate(type, slices, count, srgb);
|
||||
|
||||
luax_pushtype(L, Texture, texture);
|
||||
lovrRelease(&texture->ref);
|
||||
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }
|
||||
};
|
|
@ -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 }
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
#include "graphics/canvas.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "math/mat4.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -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);
|
|
@ -1,7 +1,5 @@
|
|||
#include "graphics/texture.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "math/mat4.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "math/mat4.h"
|
||||
#include "math/quat.h"
|
||||
#include "util.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "graphics/canvas.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue