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 vec4 color; // painter color
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
varying vec2 textureCoords; // map texture coords
void main()
{
gl_FragColor = texture2D(texture, textureCoords);
gl_FragColor = texture2D(tex0, texCoord);
}

View File

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

View File

@ -47,6 +47,11 @@ public:
m_textureVertexBuffer.addRect(src);
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 addRepeatedRects(const Rect& dest, const Rect& src);

View File

@ -77,8 +77,10 @@ void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, cons
return;
m_coordsBuffer.clear();
m_coordsBuffer.addRect(dest, src);
drawTextureCoords(m_coordsBuffer, texture);
m_coordsBuffer.addQuad(dest, src);
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)

View File

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

View File

@ -30,14 +30,17 @@
class PainterShaderProgram : public ShaderProgram
{
enum {
VERTEX_COORDS_ATTR = 0,
TEXTURE_COORDS_ATTR = 1,
VERTEX_ATTR = 0,
TEXCOORD_ATTR = 1,
PROJECTION_MATRIX_UNIFORM = 0,
TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1,
COLOR_UNIFORM = 2,
OPACITY_UNIFORM = 3,
TEXTURE_UNIFORM = 4,
TIME_UNIFORM = 5
TIME_UNIFORM = 4,
TEX0_UNIFORM = 5,
TEX1_UNIFORM = 6,
//TEX2_UNIFORM = 7,
//TEX3_UNIFORM = 8,
};
public:
enum DrawMode {
@ -52,14 +55,20 @@ public:
void setProjectionMatrix(const Matrix3& projectionMatrix);
void setColor(const Color& color);
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 draw(CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles);
private:
DrawMode m_drawMode;
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;
};

View File

@ -20,15 +20,6 @@
* 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\
highp vec4 calculatePosition();\n\
void main() {\n\
@ -36,21 +27,21 @@ static const std::string glslMainVertexShader = "\n\
}\n";
static const std::string glslMainWithTexCoordsVertexShader = "\n\
attribute highp vec2 textureCoord;\n\
uniform highp mat2 textureTransformMatrix;\n\
varying highp vec2 textureCoords;\n\
attribute highp vec2 a_texCoord;\n\
uniform highp mat2 texTransformMatrix;\n\
varying highp vec2 texCoord;\n\
highp vec4 calculatePosition();\n\
void main()\n\
{\n\
gl_Position = calculatePosition();\n\
textureCoords = textureTransformMatrix * textureCoord;\n\
texCoord = texTransformMatrix * a_texCoord;\n\
}\n";
static std::string glslPositionOnlyVertexShader = "\n\
attribute highp vec2 vertexCoord;\n\
attribute highp vec2 a_vertex;\n\
uniform highp mat3 projectionMatrix;\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";
static const std::string glslMainFragmentShader = "\n\
@ -62,11 +53,11 @@ static const std::string glslMainFragmentShader = "\n\
}\n";
static const std::string glslTextureSrcFragmentShader = "\n\
varying mediump vec2 textureCoords;\n\
varying mediump vec2 texCoord;\n\
uniform lowp vec4 color;\n\
uniform sampler2D texture;\n\
uniform sampler2D tex0;\n\
lowp vec4 calculatePixel() {\n\
return texture2D(texture, textureCoords) * color;\n\
return texture2D(tex0, texCoord) * color;\n\
}\n";
static const std::string glslSolidColorFragmentShader = "\n\

View File

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

View File

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

View File

@ -44,6 +44,7 @@ void UIFrameCounter::drawSelf()
m_fpsText = Fw::formatString("FPS: %d", m_frameCount);
m_lastFrameTicks = g_clock.ticks();
m_frameCount = 0;
dump << m_fpsText;
}
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(LEGS_COLOR_UNIFORM, "legsColor");
outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor");
outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture");
}
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);
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,
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");
}
g_painter.setCustomProgram(itemProgram);
itemProgram->bind();
itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id);
//itemProgram->bind();
//itemProgram->setUniformValue(ITEM_ID_UNIFORM, (int)m_id);
// now we can draw the item
internalDraw(dest, scaleFactor, xPattern, yPattern, zPattern, animationPhase);