Improve CanvasState;

This commit is contained in:
bjorn 2017-01-11 20:26:08 -08:00
parent 9f43f84577
commit eba3996984
6 changed files with 67 additions and 46 deletions

View File

@ -17,9 +17,10 @@ void lovrGraphicsInit() {
for (int i = 0; i < MAX_TRANSFORMS; i++) { for (int i = 0; i < MAX_TRANSFORMS; i++) {
state.transforms[i] = mat4_init(); state.transforms[i] = mat4_init();
} }
state.canvases[0].framebuffer = 0; for (int i = 0; i < MAX_CANVASES; i++) {
glGetIntegerv(GL_VIEWPORT, state.canvases[0].viewport); state.canvases[i] = malloc(sizeof(CanvasState));
state.canvases[0].isSystem = 1; state.canvases[i]->projection = mat4_init();
}
state.defaultShader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader); state.defaultShader = lovrShaderCreate(lovrDefaultVertexShader, lovrDefaultFragmentShader);
state.skyboxShader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader); state.skyboxShader = lovrShaderCreate(lovrSkyboxVertexShader, lovrSkyboxFragmentShader);
int uniformId = lovrShaderGetUniformId(state.skyboxShader, "cube"); int uniformId = lovrShaderGetUniformId(state.skyboxShader, "cube");
@ -40,6 +41,10 @@ void lovrGraphicsDestroy() {
for (int i = 0; i < MAX_TRANSFORMS; i++) { for (int i = 0; i < MAX_TRANSFORMS; i++) {
mat4_deinit(state.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.defaultShader->ref);
lovrRelease(&state.skyboxShader->ref); lovrRelease(&state.skyboxShader->ref);
lovrRelease(&state.defaultTexture->ref); lovrRelease(&state.defaultTexture->ref);
@ -53,7 +58,9 @@ void lovrGraphicsDestroy() {
void lovrGraphicsReset() { void lovrGraphicsReset() {
state.transform = 0; state.transform = 0;
state.canvas = 0; state.canvas = 0;
lovrGraphicsSetViewport(0, 0, lovrGraphicsGetWidth(), lovrGraphicsGetHeight());
lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180); // TODO customize via lovr.conf lovrGraphicsSetProjection(.1f, 100.f, 67 * M_PI / 180); // TODO customize via lovr.conf
lovrGraphicsBindFramebuffer(0);
lovrGraphicsSetShader(NULL); lovrGraphicsSetShader(NULL);
lovrGraphicsBindTexture(NULL); lovrGraphicsBindTexture(NULL);
lovrGraphicsSetBackgroundColor(0, 0, 0, 0); lovrGraphicsSetBackgroundColor(0, 0, 0, 0);
@ -89,7 +96,7 @@ void lovrGraphicsPresent() {
void lovrGraphicsPrepare() { void lovrGraphicsPrepare() {
Shader* shader = lovrGraphicsGetShader(); Shader* shader = lovrGraphicsGetShader();
mat4 transform = state.transforms[state.transform]; 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); lovrShaderBind(shader, transform, projection, state.color, 0);
} }
@ -192,7 +199,11 @@ void lovrGraphicsBindTexture(Texture* texture) {
void lovrGraphicsSetProjection(float near, float far, float fov) { void lovrGraphicsSetProjection(float near, float far, float fov) {
int width, height; int width, height;
glfwGetWindowSize(window, &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() { float lovrGraphicsGetLineWidth() {
@ -274,17 +285,12 @@ int lovrGraphicsGetHeight() {
return height; return height;
} }
void lovrGraphicsPushCanvas(CanvasState canvasState) { void lovrGraphicsPushCanvas() {
if (!canvasState.isSystem && !state.canvases[state.canvas].isSystem) { if (++state.canvas >= MAX_CANVASES) {
lovrGraphicsPopCanvas();
} else if (++state.canvas >= MAX_CANVASES) {
error("Canvas overflow"); error("Canvas overflow");
} }
int* viewport = canvasState.viewport; memcpy(state.canvases[state.canvas], state.canvases[state.canvas - 1], sizeof(CanvasState));
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glBindFramebuffer(GL_FRAMEBUFFER, canvasState.framebuffer);
state.canvases[state.canvas] = canvasState;
} }
void lovrGraphicsPopCanvas() { void lovrGraphicsPopCanvas() {
@ -292,10 +298,22 @@ void lovrGraphicsPopCanvas() {
error("Canvas underflow"); error("Canvas underflow");
} }
CanvasState* canvasState = &state.canvases[state.canvas]; int* viewport = state.canvases[state.canvas]->viewport;
int* viewport = canvasState->viewport; lovrGraphicsSetViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); lovrGraphicsBindFramebuffer(state.canvases[state.canvas]->framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, canvasState->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 // Transforms

View File

@ -40,9 +40,8 @@ typedef struct {
typedef struct CanvasState { typedef struct CanvasState {
int framebuffer; int framebuffer;
float projection[16]; mat4 projection;
int viewport[4]; int viewport[4];
int isSystem;
} CanvasState; } CanvasState;
typedef struct { typedef struct {
@ -53,7 +52,7 @@ typedef struct {
int transform; int transform;
mat4 transforms[MAX_TRANSFORMS]; mat4 transforms[MAX_TRANSFORMS];
int canvas; int canvas;
CanvasState canvases[MAX_CANVASES]; CanvasState* canvases[MAX_CANVASES];
unsigned int color; unsigned int color;
char colorMask; char colorMask;
int isScissorEnabled; int isScissorEnabled;
@ -96,6 +95,7 @@ Shader* lovrGraphicsGetShader();
void lovrGraphicsSetShader(Shader* shader); void lovrGraphicsSetShader(Shader* shader);
void lovrGraphicsBindTexture(Texture* texture); void lovrGraphicsBindTexture(Texture* texture);
void lovrGraphicsSetProjection(float near, float far, float fov); void lovrGraphicsSetProjection(float near, float far, float fov);
void lovrGraphicsSetProjectionRaw(mat4 projection);
float lovrGraphicsGetLineWidth(); float lovrGraphicsGetLineWidth();
void lovrGraphicsSetLineWidth(float width); void lovrGraphicsSetLineWidth(float width);
float lovrGraphicsGetPointSize(); float lovrGraphicsGetPointSize();
@ -110,8 +110,10 @@ int lovrGraphicsIsWireframe();
void lovrGraphicsSetWireframe(int wireframe); void lovrGraphicsSetWireframe(int wireframe);
int lovrGraphicsGetWidth(); int lovrGraphicsGetWidth();
int lovrGraphicsGetHeight(); int lovrGraphicsGetHeight();
void lovrGraphicsPushCanvas(CanvasState canvasState); void lovrGraphicsPushCanvas();
void lovrGraphicsPopCanvas(); void lovrGraphicsPopCanvas();
void lovrGraphicsSetViewport(int x, int y, int w, int h);
void lovrGraphicsBindFramebuffer(int framebuffer);
// Transforms // Transforms
int lovrGraphicsPush(); int lovrGraphicsPush();

View File

@ -48,20 +48,16 @@ void lovrTextureBind(Texture* texture) {
glBindTexture(GL_TEXTURE_2D, texture->id); glBindTexture(GL_TEXTURE_2D, texture->id);
} }
CanvasState lovrTextureGetCanvasState(Texture* texture) { void lovrTextureBindFramebuffer(Texture* texture) {
if (!texture->fbo) { if (!texture->fbo) {
error("Texture cannot be used as a canvas"); error("Texture cannot be used as a canvas");
} }
CanvasState canvasState = { lovrGraphicsBindFramebuffer(texture->fbo);
.framebuffer = texture->fbo, lovrGraphicsSetViewport(0, 0, texture->textureData->width, texture->textureData->height);
.viewport = { 0, 0, texture->textureData->width, texture->textureData->height }, if (0) {
.isSystem = 0 // lovrGraphicsSetProjection(); // TODO ortho
}; }
mat4_setIdentity(canvasState.projection); // TODO
return canvasState;
} }
int lovrTextureGetHeight(Texture* texture) { int lovrTextureGetHeight(Texture* texture) {

View File

@ -42,7 +42,7 @@ Texture* lovrTextureCreate(TextureData* textureData, int hasFramebuffer);
void lovrTextureDestroy(const Ref* ref); void lovrTextureDestroy(const Ref* ref);
void lovrTextureDataDestroy(TextureData* textureData); void lovrTextureDataDestroy(TextureData* textureData);
void lovrTextureBind(Texture* texture); void lovrTextureBind(Texture* texture);
struct CanvasState lovrTextureGetCanvasState(Texture* texture); void lovrTextureBindFramebuffer(Texture* texture);
void lovrTextureRefresh(Texture* texture); void lovrTextureRefresh(Texture* texture);
int lovrTextureGetHeight(Texture* texture); int lovrTextureGetHeight(Texture* texture);
int lovrTextureGetWidth(Texture* texture); int lovrTextureGetWidth(Texture* texture);

View File

@ -484,50 +484,53 @@ void* viveControllerGetModel(void* headset, Controller* controller, ControllerMo
void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata) { void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata) {
Vive* vive = (Vive*) headset; Vive* vive = (Vive*) headset;
CanvasState canvasState = { float projectionMatrix[16], headMatrix[16], eyeMatrix[16];
.framebuffer = vive->framebuffer,
.viewport = { 0, 0, vive->renderWidth, vive->renderHeight },
.isSystem = 1
};
float headMatrix[16], eyeMatrix[16];
float (*matrix)[4]; float (*matrix)[4];
float near = vive->clipNear;
float far = vive->clipFar;
lovrGraphicsPushCanvas();
lovrGraphicsSetViewport(0, 0, vive->renderWidth, vive->renderHeight);
vive->isRendering = 1; vive->isRendering = 1;
vive->compositor->WaitGetPoses(vive->renderPoses, 16, NULL, 0); vive->compositor->WaitGetPoses(vive->renderPoses, 16, NULL, 0);
// Head transform
matrix = vive->renderPoses[vive->headsetIndex].mDeviceToAbsoluteTracking.m; matrix = vive->renderPoses[vive->headsetIndex].mDeviceToAbsoluteTracking.m;
mat4_invert(mat4_fromMat34(headMatrix, matrix)); mat4_invert(mat4_fromMat34(headMatrix, matrix));
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
EVREye eye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right; EVREye eye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
// Eye transform
matrix = vive->system->GetEyeToHeadTransform(eye).m; matrix = vive->system->GetEyeToHeadTransform(eye).m;
mat4_invert(mat4_fromMat34(eyeMatrix, matrix)); mat4_invert(mat4_fromMat34(eyeMatrix, matrix));
mat4 transformMatrix = mat4_multiply(eyeMatrix, headMatrix); mat4 transformMatrix = mat4_multiply(eyeMatrix, headMatrix);
float near = vive->clipNear; // Projection
float far = vive->clipFar;
matrix = vive->system->GetProjectionMatrix(eye, near, far).m; matrix = vive->system->GetProjectionMatrix(eye, near, far).m;
mat4_fromMat44(canvasState.projection, matrix); mat4_fromMat44(projectionMatrix, matrix);
// Render
glEnable(GL_MULTISAMPLE); glEnable(GL_MULTISAMPLE);
lovrGraphicsBindFramebuffer(vive->framebuffer);
lovrGraphicsPushCanvas(canvasState);
lovrGraphicsClear(1, 1); lovrGraphicsClear(1, 1);
lovrGraphicsPush(); lovrGraphicsPush();
lovrGraphicsOrigin(); lovrGraphicsOrigin();
lovrGraphicsMatrixTransform(transformMatrix); lovrGraphicsMatrixTransform(transformMatrix);
lovrGraphicsSetProjectionRaw(projectionMatrix);
callback(i, userdata); callback(i, userdata);
lovrGraphicsPop(); lovrGraphicsPop();
lovrGraphicsPopCanvas(); lovrGraphicsBindFramebuffer(0);
glDisable(GL_MULTISAMPLE); glDisable(GL_MULTISAMPLE);
// Blit
glBindFramebuffer(GL_READ_FRAMEBUFFER, vive->framebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, vive->framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, vive->resolveFramebuffer); 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); 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_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
// Submit
uintptr_t texture = (uintptr_t) vive->resolveTexture; uintptr_t texture = (uintptr_t) vive->resolveTexture;
ETextureType textureType = ETextureType_TextureType_OpenGL; ETextureType textureType = ETextureType_TextureType_OpenGL;
Texture_t eyeTexture = { (void*) texture, textureType, EColorSpace_ColorSpace_Gamma }; Texture_t eyeTexture = { (void*) texture, textureType, EColorSpace_ColorSpace_Gamma };
@ -536,4 +539,5 @@ void viveRenderTo(void* headset, headsetRenderCallback callback, void* userdata)
} }
vive->isRendering = 0; vive->isRendering = 0;
lovrGraphicsPopCanvas();
} }

View File

@ -61,7 +61,8 @@ int l_lovrTextureGetWrap(lua_State* L) {
int l_lovrTextureRenderTo(lua_State* L) { int l_lovrTextureRenderTo(lua_State* L) {
Texture* texture = luax_checktype(L, 1, Texture); Texture* texture = luax_checktype(L, 1, Texture);
lovrGraphicsPushCanvas(lovrTextureGetCanvasState(texture)); lovrGraphicsPushCanvas();
lovrTextureBindFramebuffer(texture);
lua_settop(L, 2); lua_settop(L, 2);
lua_call(L, 0, 0); lua_call(L, 0, 0);
lovrGraphicsPopCanvas(); lovrGraphicsPopCanvas();