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;
|
||||
)
|
||||
|
||||
Vec4 value;
|
||||
Color value;
|
||||
GUARD_EXC( value = b->getPixel(x, y); );
|
||||
|
||||
Color *color = new Color(value);
|
||||
|
@ -223,7 +223,7 @@ RB_METHOD(bitmapSetPixel)
|
|||
|
||||
color = getPrivateDataCheck<Color>(colorObj, ColorType);
|
||||
|
||||
GUARD_EXC( b->setPixel(x, y, color->norm); );
|
||||
GUARD_EXC( b->setPixel(x, y, *color); );
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ MRB_METHOD(bitmapGetPixel)
|
|||
return mrb_nil_value();
|
||||
)
|
||||
|
||||
Vec4 value;
|
||||
Color value;
|
||||
GUARD_EXC( value = b->getPixel(x, y); )
|
||||
|
||||
Color *color = new Color(value);
|
||||
|
@ -215,7 +215,7 @@ MRB_METHOD(bitmapSetPixel)
|
|||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -55,10 +55,6 @@ struct BitmapPrivate
|
|||
{
|
||||
TEXFBO gl;
|
||||
|
||||
/* 'setPixel()' calls are cached and executed
|
||||
* in batches on 'flush()' */
|
||||
PointArray pointArray;
|
||||
|
||||
Font *font;
|
||||
|
||||
/* "Mega surfaces" are a hack to allow Tilesets to be used
|
||||
|
@ -154,32 +150,9 @@ struct BitmapPrivate
|
|||
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,
|
||||
const Vec4 &color)
|
||||
{
|
||||
flushPoints();
|
||||
|
||||
bindFBO();
|
||||
|
||||
glState.scissorTest.pushSet(true);
|
||||
|
@ -271,7 +244,6 @@ Bitmap::Bitmap(const Bitmap &other)
|
|||
|
||||
p->gl = shState->texPool().request(other.width(), other.height());
|
||||
|
||||
other.flush();
|
||||
blt(0, 0, other, rect());
|
||||
}
|
||||
|
||||
|
@ -368,8 +340,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
if (opacity == 255 && !p->touchesTaintedArea(destRect))
|
||||
{
|
||||
/* Fast blit */
|
||||
flush();
|
||||
|
||||
FBO::bind(source.p->gl.fbo, FBO::Read);
|
||||
FBO::bind(p->gl.fbo, FBO::Draw);
|
||||
|
||||
|
@ -379,8 +349,6 @@ void Bitmap::stretchBlt(const IntRect &destRect,
|
|||
else
|
||||
{
|
||||
/* Fragment pipeline */
|
||||
flush();
|
||||
|
||||
float normOpacity = (float) opacity / 255.0f;
|
||||
|
||||
TEXFBO &gpTex = shState->gpTexFBO(destRect.w, destRect.h);
|
||||
|
@ -666,9 +634,6 @@ void Bitmap::clear()
|
|||
|
||||
GUARD_MEGA;
|
||||
|
||||
/* Any queued points won't be visible after this anyway */
|
||||
p->pointArray.reset();
|
||||
|
||||
p->bindFBO();
|
||||
|
||||
glState.clearColor.pushSet(Vec4());
|
||||
|
@ -682,7 +647,7 @@ void Bitmap::clear()
|
|||
modified();
|
||||
}
|
||||
|
||||
Vec4 Bitmap::getPixel(int x, int y) const
|
||||
Color Bitmap::getPixel(int x, int y) const
|
||||
{
|
||||
GUARD_DISPOSED;
|
||||
|
||||
|
@ -691,24 +656,34 @@ Vec4 Bitmap::getPixel(int x, int y) const
|
|||
if (x < 0 || y < 0 || x >= width() || y >= height())
|
||||
return Vec4();
|
||||
|
||||
flush();
|
||||
|
||||
FBO::bind(p->gl.fbo, FBO::Read);
|
||||
|
||||
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();
|
||||
|
||||
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_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));
|
||||
|
||||
|
@ -724,8 +699,6 @@ void Bitmap::hueChange(int hue)
|
|||
if ((hue % 360) == 0)
|
||||
return;
|
||||
|
||||
flush();
|
||||
|
||||
TEXFBO newTex = shState->texPool().request(width(), height());
|
||||
|
||||
FloatRect texRect(rect());
|
||||
|
@ -777,8 +750,6 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
|
|||
if (str[0] == ' ' && str[1] == '\0')
|
||||
return;
|
||||
|
||||
flush();
|
||||
|
||||
TTF_Font *font = p->font->getSdlFont();
|
||||
Color *fontColor = p->font->getColor();
|
||||
|
||||
|
@ -1009,17 +980,6 @@ IntRect Bitmap::textSize(const char *str)
|
|||
|
||||
DEF_ATTR_SIMPLE(Bitmap, Font, Font*, p->font)
|
||||
|
||||
void Bitmap::flush() const
|
||||
{
|
||||
if (isDisposed())
|
||||
return;
|
||||
|
||||
if (p->megaSurface)
|
||||
return;
|
||||
|
||||
p->flushPoints();
|
||||
}
|
||||
|
||||
TEXFBO &Bitmap::getGLTypes()
|
||||
{
|
||||
return p->gl;
|
||||
|
|
|
@ -81,8 +81,8 @@ public:
|
|||
|
||||
void clear();
|
||||
|
||||
Vec4 getPixel(int x, int y) const;
|
||||
void setPixel(int x, int y, const Vec4 &color);
|
||||
Color getPixel(int x, int y) const;
|
||||
void setPixel(int x, int y, const Color &color);
|
||||
|
||||
void hueChange(int hue);
|
||||
|
||||
|
@ -105,9 +105,6 @@ public:
|
|||
DECL_ATTR(Font, Font*)
|
||||
|
||||
/* <internal> */
|
||||
/* Warning: Flushing might change the current
|
||||
* FBO binding (so don't call it during 'draw()' routines */
|
||||
void flush() const;
|
||||
TEXFBO &getGLTypes();
|
||||
SDL_Surface *megaSurface() const;
|
||||
void ensureNonMega() const;
|
||||
|
|
|
@ -216,15 +216,6 @@ namespace FBO
|
|||
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()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
|
@ -93,9 +93,6 @@ struct PlanePrivate
|
|||
updateQuadSource();
|
||||
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
|
||||
|
|
|
@ -163,9 +163,6 @@ struct SpritePrivate
|
|||
|
||||
void prepare()
|
||||
{
|
||||
if (bitmap)
|
||||
bitmap->flush();
|
||||
|
||||
updateVisibility();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -511,8 +511,6 @@ struct TilemapPrivate
|
|||
|
||||
usableATs.push_back(i);
|
||||
|
||||
autotiles[i]->flush();
|
||||
|
||||
if (autotiles[i]->width() > autotileW)
|
||||
animatedATs.push_back(i);
|
||||
}
|
||||
|
@ -623,13 +621,8 @@ struct TilemapPrivate
|
|||
/* Assembles atlas from tileset and autotile bitmaps */
|
||||
void buildAtlas()
|
||||
{
|
||||
tileset->flush();
|
||||
|
||||
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);
|
||||
|
||||
/* Clear atlas */
|
||||
|
|
|
@ -508,12 +508,6 @@ struct WindowPrivate
|
|||
{
|
||||
bool updateBaseQuadArray = false;
|
||||
|
||||
if (windowskin)
|
||||
windowskin->flush();
|
||||
|
||||
if (contents)
|
||||
contents->flush();
|
||||
|
||||
if (baseVertDirty)
|
||||
{
|
||||
buildBaseVert();
|
||||
|
|
Loading…
Reference in New Issue