GBA Video: Add transformed objects to GL

This commit is contained in:
Vicki Pfau 2019-05-13 00:55:26 -07:00
parent bd69c9fb26
commit c15dedf3f4
2 changed files with 35 additions and 15 deletions

View File

@ -95,7 +95,7 @@ struct GBAVideoGLRenderer {
unsigned vramDirty; unsigned vramDirty;
GLuint bgProgram[6]; GLuint bgProgram[6];
GLuint objProgram[4]; GLuint objProgram[2];
GLuint compositeProgram; GLuint compositeProgram;

View File

@ -187,7 +187,7 @@ static const char* const _renderMode2 =
" flags = inflags / flagCoeff;\n" " flags = inflags / flagCoeff;\n"
"}"; "}";
static const char* const _renderObjNoTransform = static const char* const _renderObj =
"varying vec2 texCoord;\n" "varying vec2 texCoord;\n"
"uniform sampler2D vram;\n" "uniform sampler2D vram;\n"
"uniform sampler2D palette;\n" "uniform sampler2D palette;\n"
@ -195,6 +195,8 @@ static const char* const _renderObjNoTransform =
"uniform int stride;\n" "uniform int stride;\n"
"uniform int localPalette;\n" "uniform int localPalette;\n"
"uniform ivec3 inflags;\n" "uniform ivec3 inflags;\n"
"uniform mat2x2 transform;\n"
"uniform ivec4 dims;\n"
"out vec4 color;\n" "out vec4 color;\n"
"out vec3 flags;\n" "out vec3 flags;\n"
"const vec3 flagCoeff = vec3(32., 8., 4.);\n" "const vec3 flagCoeff = vec3(32., 8., 4.);\n"
@ -202,7 +204,10 @@ static const char* const _renderObjNoTransform =
"vec4 renderTile(int tile, int paletteId, ivec2 localCoord);\n" "vec4 renderTile(int tile, int paletteId, ivec2 localCoord);\n"
"void main() {\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" " color = renderTile((coord.x >> 3) + (coord.y >> 3) * stride, 16 + localPalette, coord & 7);\n"
" flags = inflags / flagCoeff;\n" " flags = inflags / flagCoeff;\n"
"}"; "}";
@ -378,8 +383,6 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
glRenderer->compositeProgram = glCreateProgram(); glRenderer->compositeProgram = glCreateProgram();
glRenderer->objProgram[0] = glCreateProgram(); glRenderer->objProgram[0] = glCreateProgram();
glRenderer->objProgram[1] = glCreateProgram(); glRenderer->objProgram[1] = glCreateProgram();
glRenderer->objProgram[2] = glCreateProgram();
glRenderer->objProgram[3] = glCreateProgram();
glRenderer->bgProgram[0] = glCreateProgram(); glRenderer->bgProgram[0] = glCreateProgram();
glRenderer->bgProgram[1] = glCreateProgram(); glRenderer->bgProgram[1] = glCreateProgram();
glRenderer->bgProgram[2] = glCreateProgram(); glRenderer->bgProgram[2] = glCreateProgram();
@ -416,13 +419,13 @@ void GBAVideoGLRendererInit(struct GBAVideoRenderer* renderer) {
shaderBuffer[2] = _fetchTileNoOverflow; shaderBuffer[2] = _fetchTileNoOverflow;
_compileShader(glRenderer, glRenderer->bgProgram[3], shaderBuffer, 3, vs, log); _compileShader(glRenderer, glRenderer->bgProgram[3], shaderBuffer, 3, vs, log);
shaderBuffer[1] = _renderObjNoTransform; shaderBuffer[1] = _renderObj;
shaderBuffer[2] = _renderTile16; shaderBuffer[2] = _renderTile16;
_compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log); _compileShader(glRenderer, glRenderer->objProgram[0], shaderBuffer, 3, vs, log);
shaderBuffer[2] = _renderTile256; shaderBuffer[2] = _renderTile256;
_compileShader(glRenderer, glRenderer->objProgram[2], shaderBuffer, 3, vs, log); _compileShader(glRenderer, glRenderer->objProgram[1], shaderBuffer, 3, vs, log);
shaderBuffer[1] = _composite; shaderBuffer[1] = _composite;
_compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log); _compileShader(glRenderer, glRenderer->compositeProgram, shaderBuffer, 2, vs, log);
@ -449,8 +452,6 @@ void GBAVideoGLRendererDeinit(struct GBAVideoRenderer* renderer) {
glDeleteProgram(glRenderer->bgProgram[6]); glDeleteProgram(glRenderer->bgProgram[6]);
glDeleteProgram(glRenderer->objProgram[0]); glDeleteProgram(glRenderer->objProgram[0]);
glDeleteProgram(glRenderer->objProgram[1]); glDeleteProgram(glRenderer->objProgram[1]);
glDeleteProgram(glRenderer->objProgram[2]);
glDeleteProgram(glRenderer->objProgram[3]);
glDeleteProgram(glRenderer->compositeProgram); glDeleteProgram(glRenderer->compositeProgram);
} }
@ -966,26 +967,45 @@ void GBAVideoGLRendererDrawSprite(struct GBAVideoGLRenderer* renderer, struct GB
spriteY -= 256; spriteY -= 256;
} }
if (GBAObjAttributesBIsVFlip(sprite->b)) { if (!GBAObjAttributesAIsTransformed(sprite->a) && GBAObjAttributesBIsVFlip(sprite->b)) {
spriteY = (y - height) + (y - spriteY) + 1; 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]); glBindFramebuffer(GL_FRAMEBUFFER, renderer->fbo[GBA_GL_FBO_OBJ]);
glViewport(x * renderer->scale, spriteY * renderer->scale, width * renderer->scale, height * renderer->scale); glViewport(x * renderer->scale, spriteY * renderer->scale, totalWidth * renderer->scale, totalHeight * renderer->scale);
glScissor(x * renderer->scale, y * renderer->scale, width * renderer->scale, renderer->scale); glScissor(x * renderer->scale, y * renderer->scale, totalWidth * renderer->scale, renderer->scale);
glUseProgram(renderer->objProgram[GBAObjAttributesAIs256Color(sprite->a) ? 2 : 0]); glUseProgram(renderer->objProgram[GBAObjAttributesAGet256Color(sprite->a)]);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderer->vramTex); glBindTexture(GL_TEXTURE_2D, renderer->vramTex);
glActiveTexture(GL_TEXTURE0 + 1); glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, renderer->paletteTex); glBindTexture(GL_TEXTURE_2D, renderer->paletteTex);
glUniform2i(0, 1, y - spriteY); 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(2, 0);
glUniform1i(3, 1); glUniform1i(3, 1);
glUniform1i(4, charBase); glUniform1i(4, charBase);
glUniform1i(5, stride); glUniform1i(5, stride);
glUniform1i(6, GBAObjAttributesCGetPalette(sprite->c)); 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); glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, _vertices);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }); glDrawBuffers(2, (GLenum[]) { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 });