Graphics: Optimize Viewport effect rendering
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.
This commit is contained in:
parent
3c0a530eba
commit
373b90af00
|
@ -216,12 +216,15 @@ set(EMBEDDED_INPUT
|
||||||
shader/hue.frag
|
shader/hue.frag
|
||||||
shader/sprite.frag
|
shader/sprite.frag
|
||||||
shader/plane.frag
|
shader/plane.frag
|
||||||
|
shader/gray.frag
|
||||||
shader/bitmapBlit.frag
|
shader/bitmapBlit.frag
|
||||||
|
shader/flatColor.frag
|
||||||
shader/simple.frag
|
shader/simple.frag
|
||||||
shader/simpleColor.frag
|
shader/simpleColor.frag
|
||||||
shader/simpleAlpha.frag
|
shader/simpleAlpha.frag
|
||||||
shader/simpleAlphaUni.frag
|
shader/simpleAlphaUni.frag
|
||||||
shader/flashMap.frag
|
shader/flashMap.frag
|
||||||
|
shader/minimal.vert
|
||||||
shader/simple.vert
|
shader/simple.vert
|
||||||
shader/simpleColor.vert
|
shader/simpleColor.vert
|
||||||
shader/sprite.vert
|
shader/sprite.vert
|
||||||
|
|
3
mkxp.pro
3
mkxp.pro
|
@ -189,12 +189,15 @@ EMBED = \
|
||||||
shader/hue.frag \
|
shader/hue.frag \
|
||||||
shader/sprite.frag \
|
shader/sprite.frag \
|
||||||
shader/plane.frag \
|
shader/plane.frag \
|
||||||
|
shader/gray.frag \
|
||||||
shader/bitmapBlit.frag \
|
shader/bitmapBlit.frag \
|
||||||
|
shader/flatColor.frag \
|
||||||
shader/simple.frag \
|
shader/simple.frag \
|
||||||
shader/simpleColor.frag \
|
shader/simpleColor.frag \
|
||||||
shader/simpleAlpha.frag \
|
shader/simpleAlpha.frag \
|
||||||
shader/simpleAlphaUni.frag \
|
shader/simpleAlphaUni.frag \
|
||||||
shader/flashMap.frag \
|
shader/flashMap.frag \
|
||||||
|
shader/minimal.vert \
|
||||||
shader/simple.vert \
|
shader/simple.vert \
|
||||||
shader/simpleColor.vert \
|
shader/simpleColor.vert \
|
||||||
shader/sprite.vert \
|
shader/sprite.vert \
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
uniform lowp vec4 color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragColor = color;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
uniform mat4 projMat;
|
||||||
|
attribute vec2 position;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = projMat * vec4(position, 0, 1);
|
||||||
|
}
|
|
@ -60,6 +60,11 @@ struct Vec4
|
||||||
{
|
{
|
||||||
return (x == other.x && y == other.y && z == other.z && w == other.w);
|
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
|
struct Vec2i
|
||||||
|
@ -129,6 +134,14 @@ struct IntRect : SDL_Rect
|
||||||
SDL_Rect r = { x, y, w, h };
|
SDL_Rect r = { x, y, w, h };
|
||||||
return r;
|
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; };
|
struct StaticRect { float x, y, w, h; };
|
||||||
|
|
|
@ -170,9 +170,16 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
|
void requestViewportRender(Vec4 &c, Vec4 &f, Vec4 &t)
|
||||||
|
{
|
||||||
|
const IntRect &viewpRect = glState.scissorBox.get();
|
||||||
|
const IntRect &screenRect = geometry.rect;
|
||||||
|
|
||||||
|
if (t.w != 0.0)
|
||||||
{
|
{
|
||||||
pp.swapRender();
|
pp.swapRender();
|
||||||
|
|
||||||
|
if (!viewpRect.encloses(screenRect))
|
||||||
|
{
|
||||||
/* Scissor test _does_ affect FBO blit operations,
|
/* Scissor test _does_ affect FBO blit operations,
|
||||||
* and since we're inside the draw cycle, it will
|
* and since we're inside the draw cycle, it will
|
||||||
* be turned on, so turn it off temporarily */
|
* be turned on, so turn it off temporarily */
|
||||||
|
@ -184,23 +191,92 @@ public:
|
||||||
GLMeta::blitEnd();
|
GLMeta::blitEnd();
|
||||||
|
|
||||||
glState.scissorTest.pop();
|
glState.scissorTest.pop();
|
||||||
|
}
|
||||||
|
|
||||||
PlaneShader &shader = shState->shaders().plane;
|
GrayShader &shader = shState->shaders().gray;
|
||||||
shader.bind();
|
shader.bind();
|
||||||
shader.setColor(c);
|
shader.setGray(t.w);
|
||||||
shader.setFlash(f);
|
|
||||||
shader.setTone(t);
|
|
||||||
shader.setOpacity(1.0);
|
|
||||||
shader.applyViewportProj();
|
shader.applyViewportProj();
|
||||||
shader.setTexSize(geometry.rect.size());
|
shader.setTexSize(screenRect.size());
|
||||||
|
|
||||||
TEX::bind(pp.backBuffer().tex);
|
TEX::bind(pp.backBuffer().tex);
|
||||||
|
|
||||||
glState.blend.pushSet(false);
|
glState.blend.pushSet(false);
|
||||||
|
screenQuad.draw();
|
||||||
|
glState.blend.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool toneEffect = t.xyzHasEffect();
|
||||||
|
bool colorEffect = c.xyzHasEffect();
|
||||||
|
bool flashEffect = f.xyzHasEffect();
|
||||||
|
|
||||||
|
if (!toneEffect && !colorEffect && !flashEffect)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FlatColorShader &shader = shState->shaders().flatColor;
|
||||||
|
shader.bind();
|
||||||
|
shader.applyViewportProj();
|
||||||
|
|
||||||
|
/* 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();
|
screenQuad.draw();
|
||||||
|
}
|
||||||
|
|
||||||
glState.blend.pop();
|
if (sub.xyzHasEffect())
|
||||||
|
{
|
||||||
|
gl.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||||
|
shader.setColor(sub);
|
||||||
|
|
||||||
|
screenQuad.draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorEffect || flashEffect)
|
||||||
|
{
|
||||||
|
gl.BlendEquation(GL_FUNC_ADD);
|
||||||
|
gl.BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||||
|
GL_ZERO, GL_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colorEffect)
|
||||||
|
{
|
||||||
|
shader.setColor(c);
|
||||||
|
screenQuad.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flashEffect)
|
||||||
|
{
|
||||||
|
shader.setColor(f);
|
||||||
|
screenQuad.draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
glState.blendMode.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBrightness(float norm)
|
void setBrightness(float norm)
|
||||||
|
|
|
@ -35,11 +35,14 @@
|
||||||
#include "transSimple.frag.xxd"
|
#include "transSimple.frag.xxd"
|
||||||
#include "bitmapBlit.frag.xxd"
|
#include "bitmapBlit.frag.xxd"
|
||||||
#include "plane.frag.xxd"
|
#include "plane.frag.xxd"
|
||||||
|
#include "gray.frag.xxd"
|
||||||
|
#include "flatColor.frag.xxd"
|
||||||
#include "simple.frag.xxd"
|
#include "simple.frag.xxd"
|
||||||
#include "simpleColor.frag.xxd"
|
#include "simpleColor.frag.xxd"
|
||||||
#include "simpleAlpha.frag.xxd"
|
#include "simpleAlpha.frag.xxd"
|
||||||
#include "simpleAlphaUni.frag.xxd"
|
#include "simpleAlphaUni.frag.xxd"
|
||||||
#include "flashMap.frag.xxd"
|
#include "flashMap.frag.xxd"
|
||||||
|
#include "minimal.vert.xxd"
|
||||||
#include "simple.vert.xxd"
|
#include "simple.vert.xxd"
|
||||||
#include "simpleColor.vert.xxd"
|
#include "simpleColor.vert.xxd"
|
||||||
#include "sprite.vert.xxd"
|
#include "sprite.vert.xxd"
|
||||||
|
@ -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()
|
SimpleShader::SimpleShader()
|
||||||
{
|
{
|
||||||
INIT_SHADER(simple, simple, SimpleShader);
|
INIT_SHADER(simple, simple, SimpleShader);
|
||||||
|
@ -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()
|
TilemapShader::TilemapShader()
|
||||||
{
|
{
|
||||||
INIT_SHADER(tilemap, simple, TilemapShader);
|
INIT_SHADER(tilemap, simple, TilemapShader);
|
||||||
|
|
24
src/shader.h
24
src/shader.h
|
@ -87,6 +87,17 @@ protected:
|
||||||
GLint u_texSizeInv, u_translation;
|
GLint u_texSizeInv, u_translation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FlatColorShader : public ShaderBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FlatColorShader();
|
||||||
|
|
||||||
|
void setColor(const Vec4 &value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLint u_color;
|
||||||
|
};
|
||||||
|
|
||||||
class SimpleShader : public ShaderBase
|
class SimpleShader : public ShaderBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -191,6 +202,17 @@ private:
|
||||||
GLint u_tone, u_color, u_flash, u_opacity;
|
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
|
class TilemapShader : public ShaderBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -285,6 +307,7 @@ private:
|
||||||
/* Global object containing all available shaders */
|
/* Global object containing all available shaders */
|
||||||
struct ShaderSet
|
struct ShaderSet
|
||||||
{
|
{
|
||||||
|
FlatColorShader flatColor;
|
||||||
SimpleShader simple;
|
SimpleShader simple;
|
||||||
SimpleColorShader simpleColor;
|
SimpleColorShader simpleColor;
|
||||||
SimpleAlphaShader simpleAlpha;
|
SimpleAlphaShader simpleAlpha;
|
||||||
|
@ -292,6 +315,7 @@ struct ShaderSet
|
||||||
AlphaSpriteShader alphaSprite;
|
AlphaSpriteShader alphaSprite;
|
||||||
SpriteShader sprite;
|
SpriteShader sprite;
|
||||||
PlaneShader plane;
|
PlaneShader plane;
|
||||||
|
GrayShader gray;
|
||||||
TilemapShader tilemap;
|
TilemapShader tilemap;
|
||||||
FlashMapShader flashMap;
|
FlashMapShader flashMap;
|
||||||
TransShader trans;
|
TransShader trans;
|
||||||
|
|
Loading…
Reference in New Issue