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

View File

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

View File

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

View File

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

View File

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

View File

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