Bitmap: Make #get_pixel/#set_pixel more accurate
This gets rid of the "batch/flush" semantics for #set_pixel and instead just directly uploads the pixel color to the texture, circumventing the float conversion entirely. Also makes a lot of code simpler in many places as calling 'flush()' is no longer required for bitmaps.
This commit is contained in:
parent
1b0eb2797d
commit
e0a4dfe372
|
@ -202,7 +202,7 @@ RB_METHOD(bitmapGetPixel)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
)
|
)
|
||||||
|
|
||||||
Vec4 value;
|
Color value;
|
||||||
GUARD_EXC( value = b->getPixel(x, y); );
|
GUARD_EXC( value = b->getPixel(x, y); );
|
||||||
|
|
||||||
Color *color = new Color(value);
|
Color *color = new Color(value);
|
||||||
|
@ -223,7 +223,7 @@ RB_METHOD(bitmapSetPixel)
|
||||||
|
|
||||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||||
|
|
||||||
GUARD_EXC( b->setPixel(x, y, color->norm); );
|
GUARD_EXC( b->setPixel(x, y, *color); );
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ MRB_METHOD(bitmapGetPixel)
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
)
|
)
|
||||||
|
|
||||||
Vec4 value;
|
Color value;
|
||||||
GUARD_EXC( value = b->getPixel(x, y); )
|
GUARD_EXC( value = b->getPixel(x, y); )
|
||||||
|
|
||||||
Color *color = new Color(value);
|
Color *color = new Color(value);
|
||||||
|
@ -215,7 +215,7 @@ MRB_METHOD(bitmapSetPixel)
|
||||||
|
|
||||||
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
color = getPrivateDataCheck<Color>(mrb, colorObj, ColorType);
|
||||||
|
|
||||||
GUARD_EXC( b->setPixel(x, y, color->norm); )
|
GUARD_EXC( b->setPixel(x, y, *color); )
|
||||||
|
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,10 +55,6 @@ struct BitmapPrivate
|
||||||
{
|
{
|
||||||
TEXFBO gl;
|
TEXFBO gl;
|
||||||
|
|
||||||
/* 'setPixel()' calls are cached and executed
|
|
||||||
* in batches on 'flush()' */
|
|
||||||
PointArray pointArray;
|
|
||||||
|
|
||||||
Font *font;
|
Font *font;
|
||||||
|
|
||||||
/* "Mega surfaces" are a hack to allow Tilesets to be used
|
/* "Mega surfaces" are a hack to allow Tilesets to be used
|
||||||
|
@ -154,32 +150,9 @@ struct BitmapPrivate
|
||||||
glState.blendMode.pop();
|
glState.blendMode.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void flushPoints()
|
|
||||||
{
|
|
||||||
if (pointArray.count() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SimpleColorShader &shader = shState->shaders().simpleColor;
|
|
||||||
shader.bind();
|
|
||||||
shader.setTranslation(Vec2i());
|
|
||||||
|
|
||||||
bindFBO();
|
|
||||||
pushSetViewport(shader);
|
|
||||||
glState.blendMode.pushSet(BlendNone);
|
|
||||||
|
|
||||||
pointArray.commit();
|
|
||||||
pointArray.draw();
|
|
||||||
pointArray.reset();
|
|
||||||
|
|
||||||
glState.blendMode.pop();
|
|
||||||
popViewport();
|
|
||||||
}
|
|
||||||
|
|
||||||
void fillRect(const IntRect &rect,
|
void fillRect(const IntRect &rect,
|
||||||
const Vec4 &color)
|
const Vec4 &color)
|
||||||
{
|
{
|
||||||
flushPoints();
|
|
||||||
|
|
||||||
bindFBO();
|
bindFBO();
|
||||||
|
|
||||||
glState.scissorTest.pushSet(true);
|
glState.scissorTest.pushSet(true);
|
||||||
|
@ -271,7 +244,6 @@ Bitmap::Bitmap(const Bitmap &other)
|
||||||
|
|
||||||
p->gl = shState->texPool().request(other.width(), other.height());
|
p->gl = shState->texPool().request(other.width(), other.height());
|
||||||
|
|
||||||
other.flush();
|
|
||||||
blt(0, 0, other, rect());
|
blt(0, 0, other, rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,8 +340,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
||||||
if (opacity == 255 && !p->touchesTaintedArea(destRect))
|
if (opacity == 255 && !p->touchesTaintedArea(destRect))
|
||||||
{
|
{
|
||||||
/* Fast blit */
|
/* Fast blit */
|
||||||
flush();
|
|
||||||
|
|
||||||
FBO::bind(source.p->gl.fbo, FBO::Read);
|
FBO::bind(source.p->gl.fbo, FBO::Read);
|
||||||
FBO::bind(p->gl.fbo, FBO::Draw);
|
FBO::bind(p->gl.fbo, FBO::Draw);
|
||||||
|
|
||||||
|
@ -379,8 +349,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Fragment pipeline */
|
/* Fragment pipeline */
|
||||||
flush();
|
|
||||||
|
|
||||||
float normOpacity = (float) opacity / 255.0f;
|
float normOpacity = (float) opacity / 255.0f;
|
||||||
|
|
||||||
TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h);
|
TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h);
|
||||||
|
@ -666,9 +634,6 @@ void Bitmap::clear()
|
||||||
|
|
||||||
GUARD_MEGA;
|
GUARD_MEGA;
|
||||||
|
|
||||||
/* Any queued points won't be visible after this anyway */
|
|
||||||
p->pointArray.reset();
|
|
||||||
|
|
||||||
p->bindFBO();
|
p->bindFBO();
|
||||||
|
|
||||||
glState.clearColor.pushSet(Vec4());
|
glState.clearColor.pushSet(Vec4());
|
||||||
|
@ -682,7 +647,7 @@ void Bitmap::clear()
|
||||||
modified();
|
modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4 Bitmap::getPixel(int x, int y) const
|
Color Bitmap::getPixel(int x, int y) const
|
||||||
{
|
{
|
||||||
GUARD_DISPOSED;
|
GUARD_DISPOSED;
|
||||||
|
|
||||||
|
@ -691,24 +656,34 @@ Vec4 Bitmap::getPixel(int x, int y) const
|
||||||
if (x < 0 || y < 0 || x >= width() || y >= height())
|
if (x < 0 || y < 0 || x >= width() || y >= height())
|
||||||
return Vec4();
|
return Vec4();
|
||||||
|
|
||||||
flush();
|
|
||||||
|
|
||||||
FBO::bind(p->gl.fbo, FBO::Read);
|
FBO::bind(p->gl.fbo, FBO::Read);
|
||||||
|
|
||||||
glState.viewport.pushSet(IntRect(0, 0, width(), height()));
|
glState.viewport.pushSet(IntRect(0, 0, width(), height()));
|
||||||
Vec4 pixel = FBO::getPixel(x, y);
|
|
||||||
|
uint8_t pixel[4];
|
||||||
|
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
|
||||||
|
|
||||||
glState.viewport.pop();
|
glState.viewport.pop();
|
||||||
|
|
||||||
return pixel;
|
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bitmap::setPixel(int x, int y, const Vec4 &color)
|
void Bitmap::setPixel(int x, int y, const Color &color)
|
||||||
{
|
{
|
||||||
GUARD_DISPOSED;
|
GUARD_DISPOSED;
|
||||||
|
|
||||||
GUARD_MEGA;
|
GUARD_MEGA;
|
||||||
|
|
||||||
p->pointArray.append(Vec2(x+.5, y+.5), color);
|
uint8_t pixel[] =
|
||||||
|
{
|
||||||
|
(uint8_t) clamp<double>(color.red, 0, 255),
|
||||||
|
(uint8_t) clamp<double>(color.green, 0, 255),
|
||||||
|
(uint8_t) clamp<double>(color.blue, 0, 255),
|
||||||
|
(uint8_t) clamp<double>(color.alpha, 0, 255)
|
||||||
|
};
|
||||||
|
|
||||||
|
TEX::bind(p->gl.tex);
|
||||||
|
TEX::uploadSubImage(x, y, 1, 1, &pixel, GL_RGBA);
|
||||||
|
|
||||||
p->addTaintedArea(IntRect(x, y, 1, 1));
|
p->addTaintedArea(IntRect(x, y, 1, 1));
|
||||||
|
|
||||||
|
@ -724,8 +699,6 @@ void Bitmap::hueChange(int hue)
|
||||||
if ((hue % 360) == 0)
|
if ((hue % 360) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flush();
|
|
||||||
|
|
||||||
TEXFBO newTex = shState->texPool().request(width(), height());
|
TEXFBO newTex = shState->texPool().request(width(), height());
|
||||||
|
|
||||||
FloatRect texRect(rect());
|
FloatRect texRect(rect());
|
||||||
|
@ -777,8 +750,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
||||||
if (str[0] == ' ' && str[1] == '\0')
|
if (str[0] == ' ' && str[1] == '\0')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flush();
|
|
||||||
|
|
||||||
TTF_Font *font = p->font->getSdlFont();
|
TTF_Font *font = p->font->getSdlFont();
|
||||||
Color *fontColor = p->font->getColor();
|
Color *fontColor = p->font->getColor();
|
||||||
|
|
||||||
|
@ -1009,17 +980,6 @@ IntRect Bitmap::textSize(const char *str)
|
||||||
|
|
||||||
DEF_ATTR_SIMPLE(Bitmap, Font, Font*, p->font)
|
DEF_ATTR_SIMPLE(Bitmap, Font, Font*, p->font)
|
||||||
|
|
||||||
void Bitmap::flush() const
|
|
||||||
{
|
|
||||||
if (isDisposed())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (p->megaSurface)
|
|
||||||
return;
|
|
||||||
|
|
||||||
p->flushPoints();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEXFBO &Bitmap::getGLTypes()
|
TEXFBO &Bitmap::getGLTypes()
|
||||||
{
|
{
|
||||||
return p->gl;
|
return p->gl;
|
||||||
|
|
|
@ -81,8 +81,8 @@ public:
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
Vec4 getPixel(int x, int y) const;
|
Color getPixel(int x, int y) const;
|
||||||
void setPixel(int x, int y, const Vec4 &color);
|
void setPixel(int x, int y, const Color &color);
|
||||||
|
|
||||||
void hueChange(int hue);
|
void hueChange(int hue);
|
||||||
|
|
||||||
|
@ -105,9 +105,6 @@ public:
|
||||||
DECL_ATTR(Font, Font*)
|
DECL_ATTR(Font, Font*)
|
||||||
|
|
||||||
/* <internal> */
|
/* <internal> */
|
||||||
/* Warning: Flushing might change the current
|
|
||||||
* FBO binding (so don't call it during 'draw()' routines */
|
|
||||||
void flush() const;
|
|
||||||
TEXFBO &getGLTypes();
|
TEXFBO &getGLTypes();
|
||||||
SDL_Surface *megaSurface() const;
|
SDL_Surface *megaSurface() const;
|
||||||
void ensureNonMega() const;
|
void ensureNonMega() const;
|
||||||
|
|
|
@ -216,15 +216,6 @@ namespace FBO
|
||||||
blit(srcX, srcY, srcW, srcH, dstX, dstY, srcW, srcH, mode);
|
blit(srcX, srcY, srcW, srcH, dstX, dstY, srcW, srcH, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vec4 getPixel(int x, int y)
|
|
||||||
{
|
|
||||||
Vec4 pixel;
|
|
||||||
|
|
||||||
glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &pixel.x);
|
|
||||||
|
|
||||||
return pixel;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void clear()
|
inline void clear()
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
|
@ -93,9 +93,6 @@ struct PlanePrivate
|
||||||
updateQuadSource();
|
updateQuadSource();
|
||||||
quadSourceDirty = false;
|
quadSourceDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitmap)
|
|
||||||
bitmap->flush();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -110,67 +110,4 @@ struct ColorQuadArray
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PointArray
|
|
||||||
{
|
|
||||||
std::vector<Vertex> vertices;
|
|
||||||
VBO::ID vbo;
|
|
||||||
VAO::ID vao;
|
|
||||||
|
|
||||||
PointArray()
|
|
||||||
{
|
|
||||||
vbo = VBO::gen();
|
|
||||||
vao = VAO::gen();
|
|
||||||
|
|
||||||
VAO::bind(vao);
|
|
||||||
VBO::bind(vbo);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(Shader::Color);
|
|
||||||
glEnableVertexAttribArray(Shader::Position);
|
|
||||||
|
|
||||||
glVertexAttribPointer(Shader::Color, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::colorOffset());
|
|
||||||
glVertexAttribPointer(Shader::Position, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), Vertex::posOffset());
|
|
||||||
|
|
||||||
VAO::unbind();
|
|
||||||
VBO::unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
~PointArray()
|
|
||||||
{
|
|
||||||
VBO::del(vbo);
|
|
||||||
VAO::del(vao);
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const Vec2 &pos, const Vec4 &color)
|
|
||||||
{
|
|
||||||
Vertex vert;
|
|
||||||
vert.pos = pos;
|
|
||||||
vert.color = color;
|
|
||||||
vertices.push_back(vert);
|
|
||||||
}
|
|
||||||
|
|
||||||
void commit()
|
|
||||||
{
|
|
||||||
VBO::bind(vbo);
|
|
||||||
VBO::uploadData(vertices.size() * sizeof(Vertex), &vertices[0]);
|
|
||||||
VBO::unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reset()
|
|
||||||
{
|
|
||||||
vertices.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw()
|
|
||||||
{
|
|
||||||
VAO::bind(vao);
|
|
||||||
glDrawArrays(GL_POINTS, 0, count());
|
|
||||||
VAO::unbind();
|
|
||||||
}
|
|
||||||
|
|
||||||
int count()
|
|
||||||
{
|
|
||||||
return vertices.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QUADARRAY_H
|
#endif // QUADARRAY_H
|
||||||
|
|
|
@ -163,9 +163,6 @@ struct SpritePrivate
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
{
|
{
|
||||||
if (bitmap)
|
|
||||||
bitmap->flush();
|
|
||||||
|
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -511,8 +511,6 @@ struct TilemapPrivate
|
||||||
|
|
||||||
usableATs.push_back(i);
|
usableATs.push_back(i);
|
||||||
|
|
||||||
autotiles[i]->flush();
|
|
||||||
|
|
||||||
if (autotiles[i]->width() > autotileW)
|
if (autotiles[i]->width() > autotileW)
|
||||||
animatedATs.push_back(i);
|
animatedATs.push_back(i);
|
||||||
}
|
}
|
||||||
|
@ -623,13 +621,8 @@ struct TilemapPrivate
|
||||||
/* Assembles atlas from tileset and autotile bitmaps */
|
/* Assembles atlas from tileset and autotile bitmaps */
|
||||||
void buildAtlas()
|
void buildAtlas()
|
||||||
{
|
{
|
||||||
tileset->flush();
|
|
||||||
|
|
||||||
updateAutotileInfo();
|
updateAutotileInfo();
|
||||||
|
|
||||||
for (size_t i = 0; i < atlas.usableATs.size(); ++i)
|
|
||||||
autotiles[atlas.usableATs[i]]->flush();
|
|
||||||
|
|
||||||
TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size);
|
TileAtlas::BlitVec blits = TileAtlas::calcBlits(atlas.efTilesetH, atlas.size);
|
||||||
|
|
||||||
/* Clear atlas */
|
/* Clear atlas */
|
||||||
|
|
|
@ -508,12 +508,6 @@ struct WindowPrivate
|
||||||
{
|
{
|
||||||
bool updateBaseQuadArray = false;
|
bool updateBaseQuadArray = false;
|
||||||
|
|
||||||
if (windowskin)
|
|
||||||
windowskin->flush();
|
|
||||||
|
|
||||||
if (contents)
|
|
||||||
contents->flush();
|
|
||||||
|
|
||||||
if (baseVertDirty)
|
if (baseVertDirty)
|
||||||
{
|
{
|
||||||
buildBaseVert();
|
buildBaseVert();
|
||||||
|
|
Loading…
Reference in New Issue