Start Canvas objects;

This commit is contained in:
bjorn 2017-12-06 23:50:52 -08:00
parent 8eec247adb
commit d261e4b00d
9 changed files with 229 additions and 189 deletions

View File

@ -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 },

View File

@ -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;

19
src/api/types/canvas.c Normal file
View File

@ -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 }
};

View File

@ -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 }

118
src/graphics/canvas.c Normal file
View File

@ -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);
}

22
src/graphics/canvas.h Normal file
View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {