Skip to content

Commit

Permalink
Graphics: Optimize Viewport effect rendering
Browse files Browse the repository at this point in the history
Using the kitchen sink plane shader for viewport effects, even
if only a small part of them are active, incurs great performance
loss on mobile, so split the rendering into multiple optional
passes which additionally use the blending hardware for faster
mixing (lerping).
Also, don't mirror the PingPong textures if the viewport effect
covers the entire screen area anyway.
  • Loading branch information
Ancurio committed Dec 31, 2014
1 parent 3c0a530 commit 373b90a
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 20 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Expand Up @@ -216,12 +216,15 @@ set(EMBEDDED_INPUT
shader/hue.frag
shader/sprite.frag
shader/plane.frag
shader/gray.frag
shader/bitmapBlit.frag
shader/flatColor.frag
shader/simple.frag
shader/simpleColor.frag
shader/simpleAlpha.frag
shader/simpleAlphaUni.frag
shader/flashMap.frag
shader/minimal.vert
shader/simple.vert
shader/simpleColor.vert
shader/sprite.vert
Expand Down
3 changes: 3 additions & 0 deletions mkxp.pro
Expand Up @@ -189,12 +189,15 @@ EMBED = \
shader/hue.frag \
shader/sprite.frag \
shader/plane.frag \
shader/gray.frag \
shader/bitmapBlit.frag \
shader/flatColor.frag \
shader/simple.frag \
shader/simpleColor.frag \
shader/simpleAlpha.frag \
shader/simpleAlphaUni.frag \
shader/flashMap.frag \
shader/minimal.vert \
shader/simple.vert \
shader/simpleColor.vert \
shader/sprite.vert \
Expand Down
7 changes: 7 additions & 0 deletions shader/flatColor.frag
@@ -0,0 +1,7 @@

uniform lowp vec4 color;

void main()
{
gl_FragColor = color;
}
19 changes: 19 additions & 0 deletions shader/gray.frag
@@ -0,0 +1,19 @@

uniform sampler2D texture;
uniform lowp float gray;

varying vec2 v_texCoord;

const vec3 lumaF = vec3(.299, .587, .114);

void main()
{
/* Sample source color */
vec4 frag = texture2D(texture, v_texCoord);

/* Apply gray */
float luma = dot(frag.rgb, lumaF);
frag.rgb = mix(frag.rgb, vec3(luma), gray);

gl_FragColor = frag;
}
8 changes: 8 additions & 0 deletions shader/minimal.vert
@@ -0,0 +1,8 @@

uniform mat4 projMat;
attribute vec2 position;

void main()
{
gl_Position = projMat * vec4(position, 0, 1);
}
13 changes: 13 additions & 0 deletions src/etc-internal.h
Expand Up @@ -60,6 +60,11 @@ struct Vec4
{
return (x == other.x && y == other.y && z == other.z && w == other.w);
}

bool xyzHasEffect() const
{
return (x != 0.0 || y != 0.0 || z != 0.0);
}
};

struct Vec2i
Expand Down Expand Up @@ -129,6 +134,14 @@ struct IntRect : SDL_Rect
SDL_Rect r = { x, y, w, h };
return r;
}

bool encloses(const IntRect &o) const
{
return (x <= o.x &&
y <= o.y &&
x+w >= o.x+o.w &&
y+h >= o.y+o.h);
}
};

struct StaticRect { float x, y, w, h; };
Expand Down
116 changes: 96 additions & 20 deletions src/graphics.cpp
Expand Up @@ -171,36 +171,112 @@ class ScreenScene : public Scene

void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
{
pp.swapRender();
const IntRect &viewpRect = glState.scissorBox.get();
const IntRect &screenRect = geometry.rect;

/* Scissor test _does_ affect FBO blit operations,
* and since we're inside the draw cycle, it will
* be turned on, so turn it off temporarily */
glState.scissorTest.pushSet(false);
if (t.w != 0.0)
{
pp.swapRender();

GLMeta::blitBegin(pp.frontBuffer());
GLMeta::blitSource(pp.backBuffer());
GLMeta::blitRectangle(geometry.rect, Vec2i());
GLMeta::blitEnd();
if (!viewpRect.encloses(screenRect))
{
/* Scissor test _does_ affect FBO blit operations,
* and since we're inside the draw cycle, it will
* be turned on, so turn it off temporarily */
glState.scissorTest.pushSet(false);

GLMeta::blitBegin(pp.frontBuffer());
GLMeta::blitSource(pp.backBuffer());
GLMeta::blitRectangle(geometry.rect, Vec2i());
GLMeta::blitEnd();

glState.scissorTest.pop();
}

GrayShader &shader = shState->shaders().gray;
shader.bind();
shader.setGray(t.w);
shader.applyViewportProj();
shader.setTexSize(screenRect.size());

TEX::bind(pp.backBuffer().tex);

glState.blend.pushSet(false);
screenQuad.draw();
glState.blend.pop();
}

glState.scissorTest.pop();
bool toneEffect = t.xyzHasEffect();
bool colorEffect = c.xyzHasEffect();
bool flashEffect = f.xyzHasEffect();

PlaneShader &shader = shState->shaders().plane;
if (!toneEffect && !colorEffect && !flashEffect)
return;

FlatColorShader &shader = shState->shaders().flatColor;
shader.bind();
shader.setColor(c);
shader.setFlash(f);
shader.setTone(t);
shader.setOpacity(1.0);
shader.applyViewportProj();
shader.setTexSize(geometry.rect.size());

TEX::bind(pp.backBuffer().tex);
/* Apply tone */
if (toneEffect)
{
/* First split up additive / substractive components */
Vec4 add, sub;

if (t.x > 0)
add.x = t.x;
if (t.y > 0)
add.y = t.y;
if (t.z > 0)
add.z = t.z;

if (t.x < 0)
sub.x = -t.x;
if (t.y < 0)
sub.y = -t.y;
if (t.z < 0)
sub.z = -t.z;

/* Then apply them using hardware blending */
gl.BlendFuncSeparate(GL_ONE, GL_ONE, GL_ZERO, GL_ONE);

if (add.xyzHasEffect())
{
gl.BlendEquation(GL_FUNC_ADD);
shader.setColor(add);

screenQuad.draw();
}

if (sub.xyzHasEffect())
{
gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
shader.setColor(sub);

screenQuad.draw();
}
}

glState.blend.pushSet(false);
if (colorEffect || flashEffect)
{
gl.BlendEquation(GL_FUNC_ADD);
gl.BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ZERO, GL_ONE);
}

screenQuad.draw();
if (colorEffect)
{
shader.setColor(c);
screenQuad.draw();
}

if (flashEffect)
{
shader.setColor(f);
screenQuad.draw();
}

glState.blend.pop();
glState.blendMode.refresh();
}

void setBrightness(float norm)
Expand Down
33 changes: 33 additions & 0 deletions src/shader.cpp
Expand Up @@ -35,11 +35,14 @@
#include "transSimple.frag.xxd"
#include "bitmapBlit.frag.xxd"
#include "plane.frag.xxd"
#include "gray.frag.xxd"
#include "flatColor.frag.xxd"
#include "simple.frag.xxd"
#include "simpleColor.frag.xxd"
#include "simpleAlpha.frag.xxd"
#include "simpleAlphaUni.frag.xxd"
#include "flashMap.frag.xxd"
#include "minimal.vert.xxd"
#include "simple.vert.xxd"
#include "simpleColor.vert.xxd"
#include "sprite.vert.xxd"
Expand Down Expand Up @@ -269,6 +272,21 @@ void ShaderBase::setTranslation(const Vec2i &value)
}


FlatColorShader::FlatColorShader()
{
INIT_SHADER(minimal, flatColor, FlatColorShader);

ShaderBase::init();

GET_U(color);
}

void FlatColorShader::setColor(const Vec4 &value)
{
setVec4Uniform(u_color, value);
}


SimpleShader::SimpleShader()
{
INIT_SHADER(simple, simple, SimpleShader);
Expand Down Expand Up @@ -480,6 +498,21 @@ void PlaneShader::setOpacity(float value)
}


GrayShader::GrayShader()
{
INIT_SHADER(simple, gray, GrayShader);

ShaderBase::init();

GET_U(gray);
}

void GrayShader::setGray(float value)
{
gl.Uniform1f(u_gray, value);
}


TilemapShader::TilemapShader()
{
INIT_SHADER(tilemap, simple, TilemapShader);
Expand Down
24 changes: 24 additions & 0 deletions src/shader.h
Expand Up @@ -87,6 +87,17 @@ class ShaderBase : public Shader
GLint u_texSizeInv, u_translation;
};

class FlatColorShader : public ShaderBase
{
public:
FlatColorShader();

void setColor(const Vec4 &value);

private:
GLint u_color;
};

class SimpleShader : public ShaderBase
{
public:
Expand Down Expand Up @@ -191,6 +202,17 @@ class PlaneShader : public ShaderBase
GLint u_tone, u_color, u_flash, u_opacity;
};

class GrayShader : public ShaderBase
{
public:
GrayShader();

void setGray(float value);

private:
GLint u_gray;
};

class TilemapShader : public ShaderBase
{
public:
Expand Down Expand Up @@ -285,13 +307,15 @@ class BltShader : public ShaderBase
/* Global object containing all available shaders */
struct ShaderSet
{
FlatColorShader flatColor;
SimpleShader simple;
SimpleColorShader simpleColor;
SimpleAlphaShader simpleAlpha;
SimpleSpriteShader simpleSprite;
AlphaSpriteShader alphaSprite;
SpriteShader sprite;
PlaneShader plane;
GrayShader gray;
TilemapShader tilemap;
FlashMapShader flashMap;
TransShader trans;
Expand Down

0 comments on commit 373b90a

Please sign in to comment.