all repos — mgba @ c15dedf3f44f76abe87a40fe02db6f9a26f80123

mGBA Game Boy Advance Emulator

GBA Video: Add transformed objects to GL
Vicki Pfau vi@endrift.com
Mon, 13 May 2019 00:55:26 -0700
commit

c15dedf3f44f76abe87a40fe02db6f9a26f80123

parent

bd69c9fb26365f8876a20b385e9b9de94ed80feb

2 files changed, 35 insertions(+), 15 deletions(-)

jump to
M include/mgba/internal/gba/renderers/gl.hinclude/mgba/internal/gba/renderers/gl.h

@@ -95,7 +95,7 @@ GLuint vramTex;

unsigned vramDirty; GLuint bgProgram[6]; - GLuint objProgram[4]; + GLuint objProgram[2]; GLuint compositeProgram;
M src/gba/renderers/gl.csrc/gba/renderers/gl.c

@@ -187,7 +187,7 @@ " color = fetchTile(ivec2(mixedTransform * texCoord.x + mixedOffset));\n"

" flags = inflags / flagCoeff;\n" "}"; -static const char* const _renderObjNoTransform = +static const char* const _renderObj = "varying vec2 texCoord;\n" "uniform sampler2D vram;\n" "uniform sampler2D palette;\n"

@@ -195,6 +195,8 @@ "uniform int charBase;\n"

"uniform int stride;\n" "uniform int localPalette;\n" "uniform ivec3 inflags;\n" + "uniform mat2x2 transform;\n" + "uniform ivec4 dims;\n" "out vec4 color;\n" "out vec3 flags;\n" "const vec3 flagCoeff = vec3(32., 8., 4.);\n"

@@ -202,7 +204,10 @@

"vec4 renderTile(int tile, int paletteId, ivec2 localCoord);\n" "void main() {\n" - " ivec2 coord = ivec2(texCoord);\n" + " ivec2 coord = ivec2(transform * (texCoord - dims.zw / 2) + dims.xy / 2);\n" + " if ((coord & ~(dims.xy - 1)) != ivec2(0, 0)) {\n" + " discard;\n" + " }\n" " color = renderTile((coord.x >> 3) + (coord.y >> 3) * stride, 16 + localPalette, coord & 7);\n" " flags = inflags / flagCoeff;\n" "}";

@@ -378,8 +383,6 @@

glRenderer->compositeProgram = glCreateProgram(); glRenderer->objProgram[0] = glCreateProgram(); glRenderer->objProgram[1] = glCreateProgram(); - glRenderer->objProgram[2] = glCreateProgram(); - glRenderer->objProgram[3] = glCreateProgram(); glRenderer->bgProgram[0] = glCreateProgram(); glRenderer->bgProgram[1] = glCreateProgram(); glRenderer->bgProgram[2] = glCreateProgram();

@@ -416,13 +419,13 @@

shaderBuffer[2] = _fetchTileNoOverflow; _compileShader(glRenderer, glRenderer->bgProgram[3], shaderBuffer, 3, vs, log); - shaderBuffer[1] = _renderObjNoTransform; + shaderBuffer[1] = _renderObj; shaderBuffer[2] = _renderTile16; _compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log); shaderBuffer[2] = _renderTile256; - _compileShader(glRenderer, glRenderer->objProgram[2], shaderBuffer, 3, vs, log); + _compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log); shaderBuffer[1] = _composite; _compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);

@@ -449,8 +452,6 @@ glDeleteProgram(glRenderer->bgProgram[5]);

glDeleteProgram(glRenderer->bgProgram[6]); glDeleteProgram(glRenderer->objProgram[0]); glDeleteProgram(glRenderer->objProgram[1]); - glDeleteProgram(glRenderer->objProgram[2]); - glDeleteProgram(glRenderer->objProgram[3]); glDeleteProgram(glRenderer->compositeProgram); }

@@ -966,26 +967,45 @@ if (spriteY + height >= 256) {

spriteY -= 256; } - if (GBAObjAttributesBIsVFlip(sprite->b)) { + if (!GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesBIsVFlip(sprite->b)) { spriteY = (y - height) + (y - spriteY) + 1; } + int totalWidth = width; + int totalHeight = height; + if (GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesAIsDoubleSize(sprite->a)) { + totalWidth <<= 1; + totalHeight <<= 1; + } + glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]); - glViewport(x * renderer->scale, spriteY * renderer->scale, width * renderer->scale, height * renderer->scale); - glScissor(x * renderer->scale, y * renderer->scale, width * renderer->scale, renderer->scale); - glUseProgram(renderer->objProgram[GBAObjAttributesAIs256Color(sprite->a) ? 2 : 0]); + glViewport(x * renderer->scale, spriteY * renderer->scale, totalWidth * renderer->scale, totalHeight * renderer->scale); + glScissor(x * renderer->scale, y * renderer->scale, totalWidth * renderer->scale, renderer->scale); + glUseProgram(renderer->objProgram[GBAObjAttributesAGet256Color(sprite->a)]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, renderer->vramTex); glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_2D, renderer->paletteTex); glUniform2i(0, 1, y - spriteY); - glUniform2i(1, GBAObjAttributesBIsHFlip(sprite->b) ? -width : width, height); + glUniform2i(1, (GBAObjAttributesBIsHFlip(sprite->b) && !GBAObjAttributesAIsTransformed(sprite->a)) ? -totalWidth : totalWidth, totalHeight); glUniform1i(2, 0); glUniform1i(3, 1); glUniform1i(4, charBase); glUniform1i(5, stride); glUniform1i(6, GBAObjAttributesCGetPalette(sprite->c)); - glUniform3i(7, GBAObjAttributesCGetPriority(sprite->c) << 3, (renderer->target1Obj | (renderer->target2Obj * 2)) / 8.f, 0); + glUniform3i(7, GBAObjAttributesCGetPriority(sprite->c) << 3, renderer->target1Obj | (renderer->target2Obj * 2), 0); + if (GBAObjAttributesAIsTransformed(sprite->a)) { + struct GBAOAMMatrix mat; + LOAD_16(mat.a, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].a); + LOAD_16(mat.b, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].b); + LOAD_16(mat.c, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].c); + LOAD_16(mat.d, 0, &renderer->d.oam->mat[GBAObjAttributesBGetMatIndex(sprite->b)].d); + + glUniformMatrix2fv(8, 1, GL_FALSE, (GLfloat[]) { mat.a / 256.f, mat.c / 256.f, mat.b / 256.f, mat.d / 256.f }); + } else { + glUniformMatrix2fv(8, 1, GL_FALSE, (GLfloat[]) { 1.f, 0, 0, 1.f }); + } + glUniform4i(9, width, height, totalWidth, totalHeight); glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices); glEnableVertexAttribArray(0); glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });