optimize graphics performance

This commit is contained in:
Eduardo Bart 2012-04-08 16:28:03 -03:00
parent c93732a44a
commit 92bd1aba54
14 changed files with 121 additions and 83 deletions

View File

@ -1,11 +1,11 @@
uniform float opacity; // painter opacity uniform float opacity; // painter opacity
uniform vec4 color; // painter color uniform vec4 color; // painter color
uniform float time; // time in seconds since shader linkage uniform float time; // time in seconds since shader linkage
uniform sampler2D texture; // map texture uniform sampler2D tex0; // map texture
varying vec2 texCoord; // map texture coords
//uniform int itemId; // item id //uniform int itemId; // item id
varying vec2 textureCoords; // map texture coords
void main() void main()
{ {
gl_FragColor = texture2D(texture, textureCoords); gl_FragColor = texture2D(tex0, texCoord);
} }

View File

@ -1,13 +1,13 @@
uniform float opacity; // painter opacity uniform float opacity; // painter opacity
uniform vec4 color; // painter color uniform vec4 color; // painter color
uniform float time; // time in seconds since shader linkage uniform float time; // time in seconds since shader linkage
uniform sampler2D texture; // map texture uniform sampler2D tex0; // map texture
varying vec2 textureCoords; // map texture coords varying vec2 texCoord; // map texture coords
//uniform vec4 awareArea; //uniform vec4 awareArea;
void main() void main()
{ {
gl_FragColor = texture2D(texture, textureCoords); gl_FragColor = texture2D(tex0, texCoord);
} }
/* /*

View File

@ -2,9 +2,9 @@ uniform float opacity; // painter opacity
uniform vec4 color; // painter color uniform vec4 color; // painter color
uniform float time; // time in seconds since shader linkage uniform float time; // time in seconds since shader linkage
uniform sampler2D texture; // outfit texture uniform sampler2D tex0; // outfit texture
varying vec2 textureCoords; // outfit texture coords uniform sampler2D tex1; // outfit color mask
uniform sampler2D maskTexture; // outfit color mask varying vec2 texCoord; // outfit texture coords
uniform vec4 headColor; uniform vec4 headColor;
uniform vec4 bodyColor; uniform vec4 bodyColor;
@ -14,8 +14,8 @@ uniform vec4 feetColor;
vec4 calcOutfitPixel() vec4 calcOutfitPixel()
{ {
vec4 pixel = texture2D(texture, textureCoords); vec4 pixel = texture2D(tex0, texCoord);
vec4 maskColor = texture2D(maskTexture, textureCoords); vec4 maskColor = texture2D(tex1, texCoord);
vec4 outColor = vec4(1.0, 1.0, 1.0, 1.0); vec4 outColor = vec4(1.0, 1.0, 1.0, 1.0);
if(maskColor.r > 0.1 && maskColor.g > 0.1) if(maskColor.r > 0.1 && maskColor.g > 0.1)

View File

@ -47,6 +47,11 @@ public:
m_textureVertexBuffer.addRect(src); m_textureVertexBuffer.addRect(src);
m_hardwareCached = false; m_hardwareCached = false;
} }
void addQuad(const Rect& dest, const Rect& src) {
m_vertexBuffer.addQuad(dest);
m_textureVertexBuffer.addQuad(src);
m_hardwareCached = false;
}
void addBoudingRect(const Rect& dest, int innerLineWidth); void addBoudingRect(const Rect& dest, int innerLineWidth);
void addRepeatedRects(const Rect& dest, const Rect& src); void addRepeatedRects(const Rect& dest, const Rect& src);

View File

@ -77,8 +77,10 @@ void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, cons
return; return;
m_coordsBuffer.clear(); m_coordsBuffer.clear();
m_coordsBuffer.addRect(dest, src); m_coordsBuffer.addQuad(dest, src);
drawTextureCoords(m_coordsBuffer, texture); PainterShaderProgramPtr& program = m_customProgram ? m_customProgram : m_drawTexturedProgram;
program->setTexture(texture);
drawProgram(program, m_coordsBuffer, PainterShaderProgram::TriangleStrip);
} }
void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)

View File

@ -28,69 +28,99 @@
PainterShaderProgram::PainterShaderProgram() PainterShaderProgram::PainterShaderProgram()
{ {
m_textures.fill(std::make_tuple(-1, 0));
m_startTime = g_clock.time(); m_startTime = g_clock.time();
m_opacity = 1;
m_color = Color::white;
m_time = 0;
m_lastTexture = -1; m_lastTexture = -1;
} }
bool PainterShaderProgram::link() bool PainterShaderProgram::link()
{ {
bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); m_startTime = g_clock.time();
bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); bindAttributeLocation(VERTEX_ATTR, "a_vertex");
bindAttributeLocation(TEXCOORD_ATTR, "a_texCoord");
if(ShaderProgram::link()) { if(ShaderProgram::link()) {
bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix");
bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "texTransformMatrix");
bindUniformLocation(COLOR_UNIFORM, "color"); bindUniformLocation(COLOR_UNIFORM, "color");
bindUniformLocation(OPACITY_UNIFORM, "opacity"); bindUniformLocation(OPACITY_UNIFORM, "opacity");
bindUniformLocation(TEXTURE_UNIFORM, "texture");
bindUniformLocation(TIME_UNIFORM, "time"); bindUniformLocation(TIME_UNIFORM, "time");
bindUniformLocation(TEX0_UNIFORM, "tex0");
bindUniformLocation(TEX1_UNIFORM, "tex1");
bind();
setUniformValue(PROJECTION_MATRIX_UNIFORM, m_projectionMatrix);
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, m_textureTransformMatrix);
setUniformValue(COLOR_UNIFORM, m_color);
setUniformValue(OPACITY_UNIFORM, m_opacity);
setUniformValue(TIME_UNIFORM, m_time);
setUniformValue(TEX0_UNIFORM, 0);
setUniformValue(TEX1_UNIFORM, 1);
return true; return true;
} }
m_startTime = g_clock.time();
return false; return false;
} }
void PainterShaderProgram::setProjectionMatrix(const Matrix3& projectionMatrix) void PainterShaderProgram::setProjectionMatrix(const Matrix3& projectionMatrix)
{ {
if(projectionMatrix == m_projectionMatrix)
return;
bind(); bind();
setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix); setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix);
m_projectionMatrix = projectionMatrix;
} }
void PainterShaderProgram::setColor(const Color& color) void PainterShaderProgram::setColor(const Color& color)
{ {
if(color == m_color)
return;
bind(); bind();
setUniformValue(COLOR_UNIFORM, color); setUniformValue(COLOR_UNIFORM, color);
m_color = color;
} }
void PainterShaderProgram::setOpacity(float opacity) void PainterShaderProgram::setOpacity(float opacity)
{ {
bind(); if(m_opacity == opacity)
setUniformValue(OPACITY_UNIFORM, opacity);
}
void PainterShaderProgram::setUniformTexture(int location, const TexturePtr& texture, int index)
{
assert(index >= 0 && index <= 1);
m_textures[index] = std::make_tuple(location, texture ? texture->getId() : 0);
m_lastTexture = std::max(m_lastTexture, index);
}
void PainterShaderProgram::setTexture(const TexturePtr& texture)
{
if(!texture)
return; return;
bind(); bind();
setUniformTexture(TEXTURE_UNIFORM, texture, 0); setUniformValue(OPACITY_UNIFORM, opacity);
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, texture->getTransformMatrix()); m_opacity = opacity;
}
void PainterShaderProgram::setTexture(const TexturePtr& texture, int index)
{
assert(index >= 0 && index <= 1);
if(m_textures[index] == texture)
return;
m_textures[index] = texture;
m_lastTexture = std::max(m_lastTexture, index);
if(texture && index == 0) {
const Matrix2& textureTransformMatrix = texture->getTransformMatrix();
if(m_textureTransformMatrix != textureTransformMatrix) {
bind();
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix);
m_textureTransformMatrix = textureTransformMatrix;
}
}
} }
void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode) void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode)
{ {
bind(); bind();
setUniformValue(TIME_UNIFORM, g_clock.timeElapsed(m_startTime)); float time = g_clock.timeElapsed(m_startTime);
if(m_time != time) {
setUniformValue(TIME_UNIFORM, time);
m_time = time;
}
int vertexCount = coordsBuffer.getVertexCount(); int vertexCount = coordsBuffer.getVertexCount();
if(vertexCount == 0) if(vertexCount == 0)
@ -99,37 +129,36 @@ void PainterShaderProgram::draw(CoordsBuffer& coordsBuffer, DrawMode drawMode)
coordsBuffer.updateCaches(); coordsBuffer.updateCaches();
bool hardwareCached = coordsBuffer.isHardwareCached(); bool hardwareCached = coordsBuffer.isHardwareCached();
enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); enableAttributeArray(PainterShaderProgram::VERTEX_ATTR);
if(hardwareCached) if(hardwareCached)
coordsBuffer.getHardwareVertexBuffer()->bind(); coordsBuffer.getHardwareVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, hardwareCached ? 0 : coordsBuffer.getVertexBuffer(), 2); setAttributeArray(PainterShaderProgram::VERTEX_ATTR, hardwareCached ? 0 : coordsBuffer.getVertexBuffer(), 2);
bool hasTexture = coordsBuffer.getTextureVertexCount() != 0; bool hasTexture = coordsBuffer.getTextureVertexCount() != 0;
if(hasTexture) { if(hasTexture) {
enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); enableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
if(hardwareCached) if(hardwareCached)
coordsBuffer.getHardwareTextureVertexBuffer()->bind(); coordsBuffer.getHardwareTextureVertexBuffer()->bind();
setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, hardwareCached ? 0 : coordsBuffer.getTextureVertexBuffer(), 2); setAttributeArray(PainterShaderProgram::TEXCOORD_ATTR, hardwareCached ? 0 : coordsBuffer.getTextureVertexBuffer(), 2);
} }
if(hardwareCached) if(hardwareCached)
HardwareBuffer::unbind(HardwareBuffer::VertexBuffer); HardwareBuffer::unbind(HardwareBuffer::VertexBuffer);
for(int i=m_lastTexture;i>=0;--i) { if(m_lastTexture == 0) {
int location = std::get<0>(m_textures[i]); glBindTexture(GL_TEXTURE_2D, m_textures[0] ? m_textures[0]->getId() : 0);
uint id = std::get<1>(m_textures[i]); } else {
setUniformValue(location, i); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, m_textures[1] ? m_textures[1]->getId() : 0);
if(m_lastTexture > 0) glActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0+i); glBindTexture(GL_TEXTURE_2D, m_textures[0] ? m_textures[0]->getId() : 0);
glBindTexture(GL_TEXTURE_2D, id);
} }
glDrawArrays(drawMode, 0, vertexCount); glDrawArrays(drawMode, 0, vertexCount);
disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); disableAttributeArray(PainterShaderProgram::VERTEX_ATTR);
if(hasTexture) if(hasTexture)
disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); disableAttributeArray(PainterShaderProgram::TEXCOORD_ATTR);
} }

View File

@ -30,14 +30,17 @@
class PainterShaderProgram : public ShaderProgram class PainterShaderProgram : public ShaderProgram
{ {
enum { enum {
VERTEX_COORDS_ATTR = 0, VERTEX_ATTR = 0,
TEXTURE_COORDS_ATTR = 1, TEXCOORD_ATTR = 1,
PROJECTION_MATRIX_UNIFORM = 0, PROJECTION_MATRIX_UNIFORM = 0,
TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1,
COLOR_UNIFORM = 2, COLOR_UNIFORM = 2,
OPACITY_UNIFORM = 3, OPACITY_UNIFORM = 3,
TEXTURE_UNIFORM = 4, TIME_UNIFORM = 4,
TIME_UNIFORM = 5 TEX0_UNIFORM = 5,
TEX1_UNIFORM = 6,
//TEX2_UNIFORM = 7,
//TEX3_UNIFORM = 8,
}; };
public: public:
enum DrawMode { enum DrawMode {
@ -52,14 +55,20 @@ public:
void setProjectionMatrix(const Matrix3& projectionMatrix); void setProjectionMatrix(const Matrix3& projectionMatrix);
void setColor(const Color& color); void setColor(const Color& color);
void setOpacity(float opacity); void setOpacity(float opacity);
void setTexture(const TexturePtr& texture); void setTexture(const TexturePtr& texture, int index = 0);
void setUniformTexture(int location, const TexturePtr& texture, int index); void setUniformTexture(int location, const TexturePtr& texture, int index);
void draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); void draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
private: private:
DrawMode m_drawMode; DrawMode m_drawMode;
float m_startTime; float m_startTime;
std::array<std::tuple<int, uint>, 4> m_textures; TexturePtr m_textures[2];
Color m_color;
float m_opacity;
Matrix3 m_projectionMatrix;
Matrix2 m_textureTransformMatrix;
float m_time;
int m_lastTexture; int m_lastTexture;
}; };

View File

@ -20,15 +20,6 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
const static int VERTEX_COORDS_ATTR = 0;
const static int TEXTURE_COORDS_ATTR = 1;
const static int PROJECTION_MATRIX_UNIFORM = 0;
const static int TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1;
const static int COLOR_UNIFORM = 2;
const static int OPACITY_UNIFORM = 3;
const static int TEXTURE_UNIFORM = 4;
static const std::string glslMainVertexShader = "\n\ static const std::string glslMainVertexShader = "\n\
highp vec4 calculatePosition();\n\ highp vec4 calculatePosition();\n\
void main() {\n\ void main() {\n\
@ -36,21 +27,21 @@ static const std::string glslMainVertexShader = "\n\
}\n"; }\n";
static const std::string glslMainWithTexCoordsVertexShader = "\n\ static const std::string glslMainWithTexCoordsVertexShader = "\n\
attribute highp vec2 textureCoord;\n\ attribute highp vec2 a_texCoord;\n\
uniform highp mat2 textureTransformMatrix;\n\ uniform highp mat2 texTransformMatrix;\n\
varying highp vec2 textureCoords;\n\ varying highp vec2 texCoord;\n\
highp vec4 calculatePosition();\n\ highp vec4 calculatePosition();\n\
void main()\n\ void main()\n\
{\n\ {\n\
gl_Position = calculatePosition();\n\ gl_Position = calculatePosition();\n\
textureCoords = textureTransformMatrix * textureCoord;\n\ texCoord = texTransformMatrix * a_texCoord;\n\
}\n"; }\n";
static std::string glslPositionOnlyVertexShader = "\n\ static std::string glslPositionOnlyVertexShader = "\n\
attribute highp vec2 vertexCoord;\n\ attribute highp vec2 a_vertex;\n\
uniform highp mat3 projectionMatrix;\n\ uniform highp mat3 projectionMatrix;\n\
highp vec4 calculatePosition() {\n\ highp vec4 calculatePosition() {\n\
return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\ return vec4(projectionMatrix * vec3(a_vertex.xy, 1), 1);\n\
}\n"; }\n";
static const std::string glslMainFragmentShader = "\n\ static const std::string glslMainFragmentShader = "\n\
@ -62,11 +53,11 @@ static const std::string glslMainFragmentShader = "\n\
}\n"; }\n";
static const std::string glslTextureSrcFragmentShader = "\n\ static const std::string glslTextureSrcFragmentShader = "\n\
varying mediump vec2 textureCoords;\n\ varying mediump vec2 texCoord;\n\
uniform lowp vec4 color;\n\ uniform lowp vec4 color;\n\
uniform sampler2D texture;\n\ uniform sampler2D tex0;\n\
lowp vec4 calculatePixel() {\n\ lowp vec4 calculatePixel() {\n\
return texture2D(texture, textureCoords) * color;\n\ return texture2D(tex0, texCoord) * color;\n\
}\n"; }\n";
static const std::string glslSolidColorFragmentShader = "\n\ static const std::string glslSolidColorFragmentShader = "\n\

View File

@ -109,8 +109,10 @@ bool ShaderProgram::bind()
void ShaderProgram::release() void ShaderProgram::release()
{ {
m_currentProgram = 0; if(m_currentProgram != 0) {
glUseProgram(0); m_currentProgram = 0;
glUseProgram(0);
}
} }
std::string ShaderProgram::log() std::string ShaderProgram::log()

View File

@ -41,7 +41,7 @@ public:
void removeAllShaders(); void removeAllShaders();
virtual bool link(); virtual bool link();
bool bind(); bool bind();
void release(); static void release();
std::string log(); std::string log();
void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } void disableAttributeArray(int location) { glDisableVertexAttribArray(location); }

View File

@ -46,7 +46,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
{ {
m_size.resize(width, height); m_size.resize(width, height);
m_transformMatrix = { 1.0f/width, 0.0f, m_transformMatrix = { 1.0f/width, 0.0f,
0.0f, 1.0f/height }; 0.0f, 1.0f/height };
// gets max texture size supported by the driver // gets max texture size supported by the driver
static GLint maxTexSize = -1; static GLint maxTexSize = -1;

View File

@ -44,6 +44,7 @@ void UIFrameCounter::drawSelf()
m_fpsText = Fw::formatString("FPS: %d", m_frameCount); m_fpsText = Fw::formatString("FPS: %d", m_frameCount);
m_lastFrameTicks = g_clock.ticks(); m_lastFrameTicks = g_clock.ticks();
m_frameCount = 0; m_frameCount = 0;
dump << m_fpsText;
} }
m_frameCount++; m_frameCount++;

View File

@ -96,7 +96,6 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor");
outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor");
outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor");
outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture");
} }
int xPattern = 0, yPattern = 0, zPattern = 0; int xPattern = 0, yPattern = 0, zPattern = 0;
@ -141,7 +140,7 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase); int maskId = getSpriteId(w, h, 1, xPattern, yPattern, zPattern, animationPhase);
maskTex = g_sprites.getSpriteTexture(maskId); maskTex = g_sprites.getSpriteTexture(maskId);
} }
outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); outfitProgram->setTexture(maskTex, 1);
internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor, internalDraw(dest + (-Point(w,h)*Otc::TILE_PIXELS)*scaleFactor,
scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase); scaleFactor, w, h, xPattern, yPattern, zPattern, 0, animationPhase);

View File

@ -170,8 +170,8 @@ void Item::draw(const Point& dest, float scaleFactor, bool animate)
itemProgram->bindUniformLocation(ITEM_ID_UNIFORM, "itemId"); itemProgram->bindUniformLocation(ITEM_ID_UNIFORM, "itemId");
} }
g_painter.setCustomProgram(itemProgram); g_painter.setCustomProgram(itemProgram);
itemProgram->bind(); //itemProgram->bind();
itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id); //itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id);
// now we can draw the item // now we can draw the item
internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase); internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase);