mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Array textures can be easily drawn without a shader (resolves issue #1111).
Added love.graphics.drawLayer(texture, layerindex, …). ‘texture’ must be an array texture. Added SpriteBatch:add/setLayer. Added Quad:get/setLayer. This applies to array textures that are drawn without specifying an explicit layer index in the draw call. Added love.graphics.newQuad variants which have layer arguments. --HG-- branch : minor
This commit is contained in:
@@ -40,12 +40,12 @@ Canvas::~Canvas()
|
||||
canvasCount--;
|
||||
}
|
||||
|
||||
void Canvas::drawv(love::graphics::Graphics *gfx, const love::Matrix4 &t, const Vertex *v)
|
||||
void Canvas::draw(Graphics *gfx, Quad *q, const Matrix4 &t)
|
||||
{
|
||||
if (gfx->isCanvasActive(this))
|
||||
throw love::Exception("Cannot render a Canvas to itself!");
|
||||
|
||||
Texture::drawv(gfx, t, v);
|
||||
Texture::draw(gfx, q, t);
|
||||
}
|
||||
|
||||
} // graphics
|
||||
|
||||
@@ -57,11 +57,9 @@ public:
|
||||
virtual int getRequestedMSAA() const = 0;
|
||||
virtual ptrdiff_t getMSAAHandle() const = 0;
|
||||
|
||||
void draw(Graphics *gfx, Quad *q, const Matrix4 &t) override;
|
||||
|
||||
static int canvasCount;
|
||||
|
||||
private:
|
||||
|
||||
void drawv(Graphics *gfx, const Matrix4 &t, const Vertex *v) override;
|
||||
|
||||
}; // Canvas
|
||||
|
||||
|
||||
@@ -99,8 +99,7 @@ bool isDebugEnabled()
|
||||
|
||||
love::Type Graphics::type("graphics", &Module::type);
|
||||
|
||||
Shader::ShaderSource Graphics::defaultShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
|
||||
Shader::ShaderSource Graphics::defaultVideoShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
|
||||
Shader::ShaderSource Graphics::defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
|
||||
Graphics::Graphics()
|
||||
: width(0)
|
||||
@@ -130,16 +129,13 @@ Graphics::~Graphics()
|
||||
|
||||
defaultFont.set(nullptr);
|
||||
|
||||
if (Shader::defaultShader)
|
||||
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
|
||||
{
|
||||
Shader::defaultShader->release();
|
||||
Shader::defaultShader = nullptr;
|
||||
}
|
||||
|
||||
if (Shader::defaultVideoShader)
|
||||
{
|
||||
Shader::defaultVideoShader->release();
|
||||
Shader::defaultVideoShader = nullptr;
|
||||
if (Shader::standardShaders[i])
|
||||
{
|
||||
Shader::standardShaders[i]->release();
|
||||
Shader::standardShaders[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
delete streamBufferState.vb[0];
|
||||
@@ -390,7 +386,7 @@ void Graphics::setShader()
|
||||
{
|
||||
flushStreamDraws();
|
||||
|
||||
Shader::attachDefault();
|
||||
Shader::attachDefault(Shader::STANDARD_DEFAULT);
|
||||
|
||||
states.back().shader.set(nullptr);
|
||||
}
|
||||
@@ -692,6 +688,31 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
|
||||
* Drawing
|
||||
**/
|
||||
|
||||
void Graphics::draw(Drawable *drawable, const Matrix4 &m)
|
||||
{
|
||||
drawable->draw(this, m);
|
||||
}
|
||||
|
||||
void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m)
|
||||
{
|
||||
texture->draw(this, quad, m);
|
||||
}
|
||||
|
||||
void Graphics::drawLayer(Texture *texture, int layer, const Matrix4 &m)
|
||||
{
|
||||
texture->drawLayer(this, layer, m);
|
||||
}
|
||||
|
||||
void Graphics::drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m)
|
||||
{
|
||||
texture->drawLayer(this, layer, quad, m);
|
||||
}
|
||||
|
||||
void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount)
|
||||
{
|
||||
mesh->drawInstanced(this, m, instancecount);
|
||||
}
|
||||
|
||||
void Graphics::print(const std::vector<Font::ColoredString> &str, const Matrix4 &m)
|
||||
{
|
||||
checkSetDefaultFont();
|
||||
@@ -712,21 +733,6 @@ void Graphics::printf(const std::vector<Font::ColoredString> &str, float wrap, F
|
||||
state.font->printf(this, str, wrap, align, m, state.color);
|
||||
}
|
||||
|
||||
void Graphics::draw(Drawable *drawable, const Matrix4 &m)
|
||||
{
|
||||
drawable->draw(this, m);
|
||||
}
|
||||
|
||||
void Graphics::draw(Texture *texture, Quad *quad, const Matrix4 &m)
|
||||
{
|
||||
texture->drawq(this, quad, m);
|
||||
}
|
||||
|
||||
void Graphics::drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount)
|
||||
{
|
||||
mesh->drawInstanced(this, m, instancecount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Primitives (points, shapes, lines).
|
||||
**/
|
||||
@@ -1165,7 +1171,7 @@ Vector Graphics::inverseTransformPoint(Vector point)
|
||||
|
||||
const Shader::ShaderSource &Graphics::getCurrentDefaultShaderCode() const
|
||||
{
|
||||
return defaultShaderCode[getShaderLanguageTarget()][isGammaCorrect() ? 1 : 0];
|
||||
return defaultShaderCode[Shader::STANDARD_DEFAULT][getShaderLanguageTarget()][isGammaCorrect() ? 1 : 0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -585,6 +585,8 @@ public:
|
||||
|
||||
void draw(Drawable *drawable, const Matrix4 &m);
|
||||
void draw(Texture *texture, Quad *quad, const Matrix4 &m);
|
||||
void drawLayer(Texture *texture, int layer, const Matrix4 &m);
|
||||
void drawLayer(Texture *texture, int layer, Quad *quad, const Matrix4 &m);
|
||||
void drawInstanced(Mesh *mesh, const Matrix4 &m, int instancecount);
|
||||
|
||||
/**
|
||||
@@ -782,8 +784,7 @@ public:
|
||||
static bool getConstant(StackType in, const char *&out);
|
||||
|
||||
// Default shader code (a shader is always required internally.)
|
||||
static Shader::ShaderSource defaultShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
|
||||
static Shader::ShaderSource defaultVideoShaderCode[Shader::LANGUAGE_MAX_ENUM][2];
|
||||
static Shader::ShaderSource defaultShaderCode[Shader::STANDARD_MAX_ENUM][Shader::LANGUAGE_MAX_ENUM][2];
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -97,6 +97,9 @@ ParticleSystem::ParticleSystem(Graphics *gfx, Texture *texture, uint32 size)
|
||||
if (size == 0 || size > MAX_PARTICLES)
|
||||
throw love::Exception("Invalid ParticleSystem size.");
|
||||
|
||||
if (texture->getTextureType() != TEXTURE_2D)
|
||||
throw love::Exception("Only 2D textures can be used with ParticleSystems.");
|
||||
|
||||
sizes.push_back(1.0f);
|
||||
colors.push_back(Colorf(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
@@ -434,6 +437,9 @@ ParticleSystem::Particle *ParticleSystem::removeParticle(Particle *p)
|
||||
|
||||
void ParticleSystem::setTexture(Texture *tex)
|
||||
{
|
||||
if (texture->getTextureType() != TEXTURE_2D)
|
||||
throw love::Exception("Only 2D textures can be used with ParticleSystems.");
|
||||
|
||||
texture.set(tex);
|
||||
|
||||
if (defaultOffset)
|
||||
@@ -958,7 +964,7 @@ bool ParticleSystem::prepareDraw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
Graphics::TempTransform transform(gfx, m);
|
||||
|
||||
const Vertex *textureVerts = texture->getVertices();
|
||||
const vertex::XYf_STf *textureVerts = texture->getQuad()->getVertices();
|
||||
Vertex *pVerts = (Vertex *) buffer->map();
|
||||
Particle *p = pHead;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Quad::Quad(const Quad::Viewport &v, double sw, double sh)
|
||||
: sw(sw)
|
||||
, sh(sh)
|
||||
{
|
||||
memset(vertices, 255, sizeof(Vertex) * 4);
|
||||
arrayLayer = 0;
|
||||
refresh(v, sw, sh);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ Quad::~Quad()
|
||||
|
||||
void Quad::refresh(const Quad::Viewport &v, double sw, double sh)
|
||||
{
|
||||
viewport = v;
|
||||
this->viewport = v;
|
||||
this->sw = sw;
|
||||
this->sh = sh;
|
||||
|
||||
@@ -92,10 +92,20 @@ double Quad::getTextureHeight() const
|
||||
return sh;
|
||||
}
|
||||
|
||||
const Vertex *Quad::getVertices() const
|
||||
const vertex::XYf_STf *Quad::getVertices() const
|
||||
{
|
||||
return vertices;
|
||||
}
|
||||
|
||||
void Quad::setLayer(int layer)
|
||||
{
|
||||
arrayLayer = layer;
|
||||
}
|
||||
|
||||
int Quad::getLayer() const
|
||||
{
|
||||
return arrayLayer;
|
||||
}
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -53,11 +53,16 @@ public:
|
||||
double getTextureWidth() const;
|
||||
double getTextureHeight() const;
|
||||
|
||||
const Vertex *getVertices() const;
|
||||
const vertex::XYf_STf *getVertices() const;
|
||||
|
||||
void setLayer(int layer);
|
||||
int getLayer() const;
|
||||
|
||||
private:
|
||||
|
||||
Vertex vertices[4];
|
||||
vertex::XYf_STf vertices[4];
|
||||
|
||||
int arrayLayer;
|
||||
|
||||
Viewport viewport;
|
||||
double sw;
|
||||
|
||||
@@ -132,9 +132,9 @@ namespace graphics
|
||||
{
|
||||
|
||||
love::Type Shader::type("Shader", &Object::type);
|
||||
|
||||
Shader *Shader::current = nullptr;
|
||||
Shader *Shader::defaultShader = nullptr;
|
||||
Shader *Shader::defaultVideoShader = nullptr;
|
||||
Shader *Shader::standardShaders[Shader::STANDARD_MAX_ENUM] = {nullptr};
|
||||
|
||||
Shader::Shader(const ShaderSource &source)
|
||||
: shaderSource(source)
|
||||
@@ -151,27 +151,39 @@ Shader::Shader(const ShaderSource &source)
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
if (defaultShader == this)
|
||||
defaultShader = nullptr;
|
||||
|
||||
if (defaultVideoShader == this)
|
||||
defaultVideoShader = nullptr;
|
||||
for (int i = 0; i < STANDARD_MAX_ENUM; i++)
|
||||
{
|
||||
if (this == standardShaders[i])
|
||||
standardShaders[i] = nullptr;
|
||||
}
|
||||
|
||||
if (current == this)
|
||||
attachDefault();
|
||||
attachDefault(STANDARD_DEFAULT);
|
||||
}
|
||||
|
||||
void Shader::attachDefault()
|
||||
void Shader::attachDefault(StandardShader defaultType)
|
||||
{
|
||||
if (defaultShader)
|
||||
{
|
||||
if (current != defaultShader)
|
||||
defaultShader->attach();
|
||||
Shader *defaultshader = standardShaders[defaultType];
|
||||
|
||||
if (defaultshader == nullptr)
|
||||
{
|
||||
current = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
current = nullptr;
|
||||
if (current != defaultshader)
|
||||
defaultshader->attach();
|
||||
}
|
||||
|
||||
bool Shader::isDefaultActive()
|
||||
{
|
||||
for (int i = 0; i < STANDARD_MAX_ENUM; i++)
|
||||
{
|
||||
if (current == standardShaders[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TextureType Shader::getMainTextureType() const
|
||||
|
||||
@@ -95,6 +95,14 @@ public:
|
||||
UNIFORM_MAX_ENUM
|
||||
};
|
||||
|
||||
enum StandardShader
|
||||
{
|
||||
STANDARD_DEFAULT,
|
||||
STANDARD_VIDEO,
|
||||
STANDARD_ARRAY,
|
||||
STANDARD_MAX_ENUM
|
||||
};
|
||||
|
||||
struct ShaderSource
|
||||
{
|
||||
std::string vertex;
|
||||
@@ -137,8 +145,7 @@ public:
|
||||
static Shader *current;
|
||||
|
||||
// Pointer to the default Shader.
|
||||
static Shader *defaultShader;
|
||||
static Shader *defaultVideoShader;
|
||||
static Shader *standardShaders[STANDARD_MAX_ENUM];
|
||||
|
||||
Shader(const ShaderSource &source);
|
||||
virtual ~Shader();
|
||||
@@ -149,9 +156,14 @@ public:
|
||||
virtual void attach() = 0;
|
||||
|
||||
/**
|
||||
* Attach the default shader.
|
||||
* Attach a default shader.
|
||||
**/
|
||||
static void attachDefault();
|
||||
static void attachDefault(StandardShader defaultType);
|
||||
|
||||
/**
|
||||
* Gets whether any of the default shaders are currently active.
|
||||
**/
|
||||
static bool isDefaultActive();
|
||||
|
||||
/**
|
||||
* Returns any warnings this Shader may have generated.
|
||||
|
||||
@@ -44,7 +44,8 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag
|
||||
: texture(texture)
|
||||
, size(size)
|
||||
, next(0)
|
||||
, color(0)
|
||||
, color(255, 255, 255, 255)
|
||||
, color_active(false)
|
||||
, array_buf(nullptr)
|
||||
, quad_indices(gfx, size)
|
||||
, range_start(-1)
|
||||
@@ -53,26 +54,59 @@ SpriteBatch::SpriteBatch(Graphics *gfx, Texture *texture, int size, vertex::Usag
|
||||
if (size <= 0)
|
||||
throw love::Exception("Invalid SpriteBatch size.");
|
||||
|
||||
size_t vertex_size = sizeof(Vertex) * 4 * size;
|
||||
if (texture == nullptr)
|
||||
throw love::Exception("A texture must be used when creating a SpriteBatch.");
|
||||
|
||||
if (texture->getTextureType() == TEXTURE_2D_ARRAY)
|
||||
vertex_format = vertex::CommonFormat::XYf_STPf_RGBAub;
|
||||
else
|
||||
vertex_format = vertex::CommonFormat::XYf_STf_RGBAub;
|
||||
|
||||
format_stride = vertex::getFormatStride(vertex_format);
|
||||
|
||||
size_t vertex_size = format_stride * 4 * size;
|
||||
array_buf = gfx->newBuffer(vertex_size, nullptr, BUFFER_VERTEX, usage, Buffer::MAP_EXPLICIT_RANGE_MODIFY);
|
||||
}
|
||||
|
||||
SpriteBatch::~SpriteBatch()
|
||||
{
|
||||
delete color;
|
||||
delete array_buf;
|
||||
}
|
||||
|
||||
int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
|
||||
{
|
||||
return add(texture->getQuad(), m, index);
|
||||
}
|
||||
|
||||
int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
|
||||
{
|
||||
using namespace vertex;
|
||||
|
||||
if (vertex_format == CommonFormat::XYf_STPf_RGBAub)
|
||||
return addLayer(quad->getLayer(), quad, m, index);
|
||||
|
||||
if (index < -1 || index >= size)
|
||||
throw love::Exception("Invalid sprite index: %d", index + 1);
|
||||
|
||||
if (index == -1 && next >= size)
|
||||
setBufferSize(size * 2);
|
||||
|
||||
addv(texture->getVertices(), m, (index == -1) ? next : index);
|
||||
const XYf_STf *quadverts = quad->getVertices();
|
||||
|
||||
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
|
||||
size_t offset = (index == -1 ? next : index) * format_stride * 4;
|
||||
auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
|
||||
|
||||
m.transform(verts, quadverts, 4);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
verts[i].s = quadverts[i].s;
|
||||
verts[i].t = quadverts[i].t;
|
||||
verts[i].color = color;
|
||||
}
|
||||
|
||||
array_buf->setMappedRangeModified(offset, format_stride * 4);
|
||||
|
||||
// Increment counter.
|
||||
if (index == -1)
|
||||
@@ -81,15 +115,44 @@ int SpriteBatch::add(const Matrix4 &m, int index /*= -1*/)
|
||||
return index;
|
||||
}
|
||||
|
||||
int SpriteBatch::addq(Quad *quad, const Matrix4 &m, int index /*= -1*/)
|
||||
int SpriteBatch::addLayer(int layer, const Matrix4 &m, int index)
|
||||
{
|
||||
return addLayer(layer, texture->getQuad(), m, index);
|
||||
}
|
||||
|
||||
int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
|
||||
{
|
||||
using namespace vertex;
|
||||
|
||||
if (vertex_format != CommonFormat::XYf_STPf_RGBAub)
|
||||
throw love::Exception("addLayer can only be called on a SpriteBatch that uses an Array Texture!");
|
||||
|
||||
if (index < -1 || index >= size)
|
||||
throw love::Exception("Invalid sprite index: %d", index + 1);
|
||||
|
||||
if (layer < 0 || layer >= texture->getLayerCount())
|
||||
throw love::Exception("Invalid layer: %d (Texture has %d layers)", layer + 1, texture->getLayerCount());
|
||||
|
||||
if (index == -1 && next >= size)
|
||||
setBufferSize(size * 2);
|
||||
|
||||
addv(quad->getVertices(), m, (index == -1) ? next : index);
|
||||
const XYf_STf *quadverts = quad->getVertices();
|
||||
|
||||
// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
|
||||
size_t offset = (index == -1 ? next : index) * format_stride * 4;
|
||||
auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
|
||||
|
||||
m.transform(verts, quadverts, 4);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
verts[i].s = quadverts[i].s;
|
||||
verts[i].t = quadverts[i].t;
|
||||
verts[i].p = (float) layer;
|
||||
verts[i].color = color;
|
||||
}
|
||||
|
||||
array_buf->setMappedRangeModified(offset, format_stride * 4);
|
||||
|
||||
// Increment counter.
|
||||
if (index == -1)
|
||||
@@ -111,6 +174,9 @@ void SpriteBatch::flush()
|
||||
|
||||
void SpriteBatch::setTexture(Texture *newtexture)
|
||||
{
|
||||
if (texture->getTextureType() != newtexture->getTextureType())
|
||||
throw love::Exception("Texture must have the same texture type as the SpriteBatch's previous texture.");
|
||||
|
||||
texture.set(newtexture);
|
||||
}
|
||||
|
||||
@@ -121,20 +187,19 @@ Texture *SpriteBatch::getTexture() const
|
||||
|
||||
void SpriteBatch::setColor(const Color &color)
|
||||
{
|
||||
if (!this->color)
|
||||
this->color = new Color(color);
|
||||
else
|
||||
*(this->color) = color;
|
||||
color_active = true;
|
||||
this->color = color;
|
||||
}
|
||||
|
||||
void SpriteBatch::setColor()
|
||||
{
|
||||
delete color;
|
||||
color = nullptr;
|
||||
color_active = false;
|
||||
color = Color(255, 255, 255, 255);
|
||||
}
|
||||
|
||||
const Color *SpriteBatch::getColor() const
|
||||
const Color &SpriteBatch::getColor(bool &active) const
|
||||
{
|
||||
active = color_active;
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -151,7 +216,7 @@ void SpriteBatch::setBufferSize(int newsize)
|
||||
if (newsize == size)
|
||||
return;
|
||||
|
||||
size_t vertex_size = sizeof(Vertex) * 4 * newsize;
|
||||
size_t vertex_size = format_stride * 4 * newsize;
|
||||
love::graphics::Buffer *new_array_buf = nullptr;
|
||||
|
||||
int new_next = std::min(next, newsize);
|
||||
@@ -162,7 +227,7 @@ void SpriteBatch::setBufferSize(int newsize)
|
||||
new_array_buf = gfx->newBuffer(vertex_size, nullptr, array_buf->getType(), array_buf->getUsage(), array_buf->getMapFlags());
|
||||
|
||||
// Copy as much of the old data into the new GLBuffer as can fit.
|
||||
size_t copy_size = sizeof(Vertex) * 4 * new_next;
|
||||
size_t copy_size = format_stride * 4 * new_next;
|
||||
array_buf->copyTo(0, copy_size, new_array_buf, 0);
|
||||
|
||||
quad_indices = QuadIndices(gfx, newsize);
|
||||
@@ -233,26 +298,5 @@ bool SpriteBatch::getDrawRange(int &start, int &count) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteBatch::addv(const Vertex *v, const Matrix4 &m, int index)
|
||||
{
|
||||
// Needed for colors.
|
||||
Vertex sprite[4] = {v[0], v[1], v[2], v[3]};
|
||||
const size_t sprite_size = 4 * sizeof(Vertex); // bytecount
|
||||
|
||||
m.transform(sprite, sprite, 4);
|
||||
|
||||
if (color != nullptr)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
sprite[i].color = *color;
|
||||
}
|
||||
|
||||
// Always keep the VBO mapped when adding data for now (it'll be unmapped
|
||||
// on draw.)
|
||||
array_buf->map();
|
||||
|
||||
array_buf->fill(index * sprite_size, sprite_size, sprite);
|
||||
}
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -54,7 +54,10 @@ public:
|
||||
virtual ~SpriteBatch();
|
||||
|
||||
int add(const Matrix4 &m, int index = -1);
|
||||
int addq(Quad *quad, const Matrix4 &m, int index = -1);
|
||||
int add(Quad *quad, const Matrix4 &m, int index = -1);
|
||||
int addLayer(int layer, const Matrix4 &m, int index = -1);
|
||||
int addLayer(int layer, Quad *quad, const Matrix4 &m, int index = -1);
|
||||
|
||||
void clear();
|
||||
|
||||
void flush();
|
||||
@@ -78,10 +81,9 @@ public:
|
||||
void setColor();
|
||||
|
||||
/**
|
||||
* Get the current color for this SpriteBatch. Returns NULL if no color is
|
||||
* set.
|
||||
* Get the current color for this SpriteBatch.
|
||||
**/
|
||||
const Color *getColor() const;
|
||||
const Color &getColor(bool &active) const;
|
||||
|
||||
/**
|
||||
* Get the number of sprites currently in this SpriteBatch.
|
||||
@@ -117,8 +119,6 @@ protected:
|
||||
**/
|
||||
void setBufferSize(int newsize);
|
||||
|
||||
void addv(const Vertex *v, const Matrix4 &m, int index);
|
||||
|
||||
StrongRef<Texture> texture;
|
||||
|
||||
// Max number of sprites in the batch.
|
||||
@@ -129,7 +129,11 @@ protected:
|
||||
|
||||
// Current color. This color, if present, will be applied to the next
|
||||
// added sprite.
|
||||
Color *color;
|
||||
Color color;
|
||||
bool color_active;
|
||||
|
||||
vertex::CommonFormat vertex_format;
|
||||
size_t format_stride;
|
||||
|
||||
love::graphics::Buffer *array_buf;
|
||||
QuadIndices quad_indices;
|
||||
|
||||
@@ -61,7 +61,6 @@ Texture::Texture(TextureType texType)
|
||||
, filter(defaultFilter)
|
||||
, wrap()
|
||||
, mipmapSharpness(defaultMipmapSharpness)
|
||||
, vertices()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -69,32 +68,10 @@ Texture::~Texture()
|
||||
{
|
||||
}
|
||||
|
||||
void Texture::initVertices()
|
||||
void Texture::initQuad()
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
vertices[i].color = Color(255, 255, 255, 255);
|
||||
|
||||
// Vertices are ordered for use with triangle strips:
|
||||
// 0---2
|
||||
// | / |
|
||||
// 1---3
|
||||
vertices[0].x = 0.0f;
|
||||
vertices[0].y = 0.0f;
|
||||
vertices[1].x = 0.0f;
|
||||
vertices[1].y = (float) height;
|
||||
vertices[2].x = (float) width;
|
||||
vertices[2].y = 0.0f;
|
||||
vertices[3].x = (float) width;
|
||||
vertices[3].y = (float) height;
|
||||
|
||||
vertices[0].s = 0.0f;
|
||||
vertices[0].t = 0.0f;
|
||||
vertices[1].s = 0.0f;
|
||||
vertices[1].t = 1.0f;
|
||||
vertices[2].s = 1.0f;
|
||||
vertices[2].t = 0.0f;
|
||||
vertices[3].s = 1.0f;
|
||||
vertices[3].t = 1.0f;
|
||||
Quad::Viewport v = {0, 0, (double) width, (double) height};
|
||||
quad.set(new Quad(v, width, height), Acquire::NORETAIN);
|
||||
}
|
||||
|
||||
TextureType Texture::getTextureType() const
|
||||
@@ -109,37 +86,81 @@ PixelFormat Texture::getPixelFormat() const
|
||||
|
||||
void Texture::draw(Graphics *gfx, const Matrix4 &m)
|
||||
{
|
||||
drawv(gfx, m, vertices);
|
||||
draw(gfx, quad, m);
|
||||
}
|
||||
|
||||
void Texture::drawq(Graphics *gfx, Quad *quad, const Matrix4 &m)
|
||||
void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform)
|
||||
{
|
||||
drawv(gfx, m, quad->getVertices());
|
||||
}
|
||||
using namespace vertex;
|
||||
|
||||
void Texture::drawv(Graphics *gfx, const Matrix4 &localTransform, const Vertex *v)
|
||||
{
|
||||
if (Shader::current)
|
||||
Shader::current->checkMainTextureType(texType);
|
||||
|
||||
Matrix4 t(gfx->getTransform(), localTransform);
|
||||
|
||||
Vertex verts[4] = {v[0], v[1], v[2], v[3]};
|
||||
t.transform(verts, v, 4);
|
||||
if (texType == TEXTURE_2D_ARRAY)
|
||||
{
|
||||
drawLayer(gfx, q->getLayer(), q, localTransform);
|
||||
return;
|
||||
}
|
||||
|
||||
Color c = toColor(gfx->getColor());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
verts[i].color = c;
|
||||
|
||||
Graphics::StreamDrawRequest req;
|
||||
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
|
||||
req.indexMode = vertex::TriangleIndexMode::QUADS;
|
||||
req.formats[0] = CommonFormat::XYf_STf_RGBAub;
|
||||
req.indexMode = TriangleIndexMode::QUADS;
|
||||
req.vertexCount = 4;
|
||||
req.texture = this;
|
||||
|
||||
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
|
||||
memcpy(data.stream[0], verts, sizeof(Vertex) * 4);
|
||||
|
||||
XYf_STf_RGBAub *verts = (XYf_STf_RGBAub *) data.stream[0];
|
||||
const XYf_STf *quadverts = q->getVertices();
|
||||
|
||||
Matrix4 t(gfx->getTransform(), localTransform);
|
||||
t.transform(verts, quadverts, 4);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
verts[i].s = quadverts[i].s;
|
||||
verts[i].t = quadverts[i].t;
|
||||
verts[i].color = c;
|
||||
}
|
||||
}
|
||||
|
||||
void Texture::drawLayer(Graphics *gfx, int layer, const Matrix4 &m)
|
||||
{
|
||||
drawLayer(gfx, layer, quad, m);
|
||||
}
|
||||
|
||||
void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m)
|
||||
{
|
||||
using namespace vertex;
|
||||
|
||||
if (texType != TEXTURE_2D_ARRAY)
|
||||
throw love::Exception("drawLayer can only be used with Array Textures!");
|
||||
|
||||
if (layer < 0 || layer >= layers)
|
||||
throw love::Exception("Invalid layer: %d (Texture has %d layers)", layer + 1, layers);
|
||||
|
||||
Color c = toColor(gfx->getColor());
|
||||
|
||||
Graphics::StreamDrawRequest req;
|
||||
req.formats[0] = CommonFormat::XYf_STPf_RGBAub;
|
||||
req.indexMode = TriangleIndexMode::QUADS;
|
||||
req.vertexCount = 4;
|
||||
req.texture = this;
|
||||
|
||||
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
|
||||
|
||||
XYf_STPf_RGBAub *verts = (XYf_STPf_RGBAub *) data.stream[0];
|
||||
const XYf_STf *quadverts = q->getVertices();
|
||||
|
||||
Matrix4 t(gfx->getTransform(), m);
|
||||
t.transform(verts, quadverts, 4);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
verts[i].s = quadverts[i].s;
|
||||
verts[i].t = quadverts[i].t;
|
||||
verts[i].p = (float) layer;
|
||||
verts[i].color = c;
|
||||
}
|
||||
}
|
||||
|
||||
int Texture::getWidth() const
|
||||
@@ -197,9 +218,9 @@ float Texture::getMipmapSharpness() const
|
||||
return mipmapSharpness;
|
||||
}
|
||||
|
||||
const Vertex *Texture::getVertices() const
|
||||
Quad *Texture::getQuad() const
|
||||
{
|
||||
return vertices;
|
||||
return quad;
|
||||
}
|
||||
|
||||
bool Texture::validateFilter(const Filter &f, bool mipmapsAllowed)
|
||||
|
||||
@@ -112,7 +112,10 @@ public:
|
||||
/**
|
||||
* Draws the texture using the specified transformation with a Quad applied.
|
||||
**/
|
||||
void drawq(Graphics *gfx, Quad *quad, const Matrix4 &m);
|
||||
virtual void draw(Graphics *gfx, Quad *quad, const Matrix4 &m);
|
||||
|
||||
void drawLayer(Graphics *gfx, int layer, const Matrix4 &m);
|
||||
virtual void drawLayer(Graphics *gfx, int layer, Quad *quad, const Matrix4 &m);
|
||||
|
||||
TextureType getTextureType() const;
|
||||
PixelFormat getPixelFormat() const;
|
||||
@@ -138,7 +141,7 @@ public:
|
||||
virtual bool setMipmapSharpness(float sharpness) = 0;
|
||||
float getMipmapSharpness() const;
|
||||
|
||||
virtual const Vertex *getVertices() const;
|
||||
Quad *getQuad() const;
|
||||
|
||||
virtual ptrdiff_t getHandle() const = 0;
|
||||
|
||||
@@ -158,8 +161,7 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
void initVertices();
|
||||
virtual void drawv(Graphics *gfx, const Matrix4 &localTransform, const Vertex *v);
|
||||
void initQuad();
|
||||
|
||||
TextureType texType;
|
||||
|
||||
@@ -167,6 +169,7 @@ protected:
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int depth;
|
||||
int layers;
|
||||
int mipmapCount;
|
||||
@@ -174,13 +177,12 @@ protected:
|
||||
int pixelWidth;
|
||||
int pixelHeight;
|
||||
|
||||
|
||||
Filter filter;
|
||||
Wrap wrap;
|
||||
|
||||
float mipmapSharpness;
|
||||
|
||||
Vertex vertices[4];
|
||||
StrongRef<Quad> quad;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -109,16 +109,18 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
gfx->flushStreamDraws();
|
||||
|
||||
love::graphics::Shader *shader = Shader::current;
|
||||
bool usingdefaultshader = (shader == Shader::defaultShader);
|
||||
bool usingdefaultshader = Shader::isDefaultActive();
|
||||
Shader *prevdefaultshader = nullptr;
|
||||
|
||||
// If we're using the default shader, substitute the video version.
|
||||
if (usingdefaultshader)
|
||||
{
|
||||
// If we're using the default shader, substitute the video version.
|
||||
Shader::defaultVideoShader->attach();
|
||||
shader = Shader::defaultVideoShader;
|
||||
prevdefaultshader = Shader::current;
|
||||
Shader::standardShaders[Shader::STANDARD_VIDEO]->attach();
|
||||
}
|
||||
|
||||
shader->setVideoTextures(images[0], images[1], images[2]);
|
||||
if (Shader::current != nullptr)
|
||||
Shader::current->setVideoTextures(images[0], images[1], images[2]);
|
||||
|
||||
Graphics::StreamDrawRequest req;
|
||||
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
|
||||
@@ -142,8 +144,8 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
gfx->flushStreamDraws();
|
||||
|
||||
if (usingdefaultshader)
|
||||
Shader::defaultShader->attach();
|
||||
if (usingdefaultshader && prevdefaultshader != nullptr)
|
||||
prevdefaultshader->attach();
|
||||
}
|
||||
|
||||
void Video::update()
|
||||
|
||||
@@ -140,7 +140,7 @@ Canvas::Canvas(const Settings &settings)
|
||||
|
||||
this->format = getSizedFormat(settings.format);
|
||||
|
||||
initVertices();
|
||||
initQuad();
|
||||
loadVolatile();
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
|
||||
@@ -268,25 +268,19 @@ bool Graphics::setMode(int width, int height, int pixelwidth, int pixelheight, b
|
||||
restoreState(states.back());
|
||||
|
||||
int gammacorrect = isGammaCorrect() ? 1 : 0;
|
||||
Shader::Language target = getShaderLanguageTarget();
|
||||
|
||||
// We always need a default shader.
|
||||
if (!Shader::defaultShader)
|
||||
for (int i = 0; i < Shader::STANDARD_MAX_ENUM; i++)
|
||||
{
|
||||
Shader::Language target = getShaderLanguageTarget();
|
||||
Shader::defaultShader = newShader(defaultShaderCode[target][gammacorrect]);
|
||||
}
|
||||
|
||||
// and a default video shader.
|
||||
if (!Shader::defaultVideoShader)
|
||||
{
|
||||
Shader::Language target = getShaderLanguageTarget();
|
||||
Shader::defaultVideoShader = newShader(defaultVideoShaderCode[target][gammacorrect]);
|
||||
if (!Shader::standardShaders[i])
|
||||
Shader::standardShaders[i] = newShader(defaultShaderCode[i][target][gammacorrect]);
|
||||
}
|
||||
|
||||
// A shader should always be active, but the default shader shouldn't be
|
||||
// returned by getShader(), so we don't do setShader(defaultShader).
|
||||
if (!Shader::current)
|
||||
Shader::defaultShader->attach();
|
||||
Shader::standardShaders[Shader::STANDARD_DEFAULT]->attach();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -343,8 +337,21 @@ void Graphics::flushStreamDraws()
|
||||
if (sbstate.vertexCount == 0 && sbstate.indexCount == 0)
|
||||
return;
|
||||
|
||||
if (Shader::current && sbstate.texture.get())
|
||||
Shader::current->checkMainTextureType(sbstate.texture->getTextureType());
|
||||
love::graphics::Shader *prevdefaultshader = nullptr;
|
||||
|
||||
if (sbstate.texture.get())
|
||||
{
|
||||
TextureType textype = sbstate.texture->getTextureType();
|
||||
|
||||
if (textype == TEXTURE_2D_ARRAY && Shader::isDefaultActive())
|
||||
{
|
||||
prevdefaultshader = Shader::current;
|
||||
Shader::standardShaders[Shader::STANDARD_ARRAY]->attach();
|
||||
}
|
||||
|
||||
if (Shader::current)
|
||||
Shader::current->checkMainTextureType(textype);
|
||||
}
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("Stream vertices flush and draw");
|
||||
|
||||
@@ -425,6 +432,9 @@ void Graphics::flushStreamDraws()
|
||||
|
||||
streamBufferState.vertexCount = 0;
|
||||
streamBufferState.indexCount = 0;
|
||||
|
||||
if (prevdefaultshader != nullptr)
|
||||
prevdefaultshader->attach();
|
||||
}
|
||||
|
||||
static void APIENTRY debugCB(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /*len*/, const GLchar *msg, const GLvoid* /*usr*/)
|
||||
|
||||
@@ -92,8 +92,8 @@ void Image::init(PixelFormat fmt, int w, int h, const Settings &settings)
|
||||
if (getMipmapCount() > 1)
|
||||
filter.mipmap = defaultMipmapFilter;
|
||||
|
||||
initQuad();
|
||||
loadVolatile();
|
||||
initVertices();
|
||||
}
|
||||
|
||||
void Image::generateMipmaps()
|
||||
|
||||
@@ -650,6 +650,10 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, s)));
|
||||
break;
|
||||
case CommonFormat::XYf_STPf:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf, s)));
|
||||
break;
|
||||
case CommonFormat::XYf_STf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf_RGBAub, s)));
|
||||
@@ -660,6 +664,11 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_UNSIGNED_SHORT, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STus_RGBAub, color.r)));
|
||||
break;
|
||||
case CommonFormat::XYf_STPf_RGBAub:
|
||||
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, x)));
|
||||
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, s)));
|
||||
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STPf_RGBAub, color.r)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,8 +60,21 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
gfx->flushStreamDraws();
|
||||
|
||||
if (Shader::current && texture.get())
|
||||
Shader::current->checkMainTextureType(texture->getTextureType());
|
||||
Shader *prevdefaultshader = nullptr;
|
||||
|
||||
if (texture.get())
|
||||
{
|
||||
TextureType textype = texture->getTextureType();
|
||||
|
||||
if (textype == TEXTURE_2D_ARRAY && Shader::isDefaultActive())
|
||||
{
|
||||
prevdefaultshader = Shader::current;
|
||||
Shader::standardShaders[Shader::STANDARD_ARRAY]->attach();
|
||||
}
|
||||
|
||||
if (Shader::current)
|
||||
Shader::current->checkMainTextureType(texture->getTextureType());
|
||||
}
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("SpriteBatch draw");
|
||||
|
||||
@@ -72,13 +85,19 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
||||
// Make sure the VBO isn't mapped when we draw (sends data to GPU if needed.)
|
||||
array_buf->unmap();
|
||||
|
||||
CommonFormat format = CommonFormat::XYf_STf_RGBAub;
|
||||
if (color == nullptr)
|
||||
format = CommonFormat::XYf_STf;
|
||||
CommonFormat format = vertex_format;
|
||||
|
||||
if (!color_active)
|
||||
{
|
||||
if (format == CommonFormat::XYf_STPf_RGBAub)
|
||||
format = CommonFormat::XYf_STPf;
|
||||
else
|
||||
format = CommonFormat::XYf_STf;
|
||||
}
|
||||
|
||||
uint32 enabledattribs = getFormatFlags(format);
|
||||
|
||||
gl.setVertexPointers(format, array_buf, getFormatStride(CommonFormat::XYf_STf_RGBAub), 0);
|
||||
gl.setVertexPointers(format, array_buf, format_stride, 0);
|
||||
|
||||
for (const auto &it : attached_attributes)
|
||||
{
|
||||
@@ -116,6 +135,9 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
gl.drawElements(GL_TRIANGLES, (GLsizei) quad_indices.getIndexCount(count), gltype, indices);
|
||||
}
|
||||
|
||||
if (prevdefaultshader != nullptr)
|
||||
prevdefaultshader->attach();
|
||||
}
|
||||
|
||||
} // opengl
|
||||
|
||||
@@ -30,8 +30,10 @@ namespace vertex
|
||||
|
||||
static_assert(sizeof(Color) == 4, "sizeof(Color) incorrect!");
|
||||
static_assert(sizeof(XYf_STf) == sizeof(float)*2 + sizeof(float)*2, "sizeof(XYf_STf) incorrect!");
|
||||
static_assert(sizeof(XYf_STPf) == sizeof(float)*2 + sizeof(float)*3, "sizeof(XYf_STPf) incorrect!");
|
||||
static_assert(sizeof(XYf_STf_RGBAub) == sizeof(float)*2 + sizeof(float)*2 + sizeof(Color), "sizeof(XYf_STf_RGBAub) incorrect!");
|
||||
static_assert(sizeof(XYf_STus_RGBAub) == sizeof(float)*2 + sizeof(uint16)*2 + sizeof(Color), "sizeof(XYf_STus_RGBAub) incorrect!");
|
||||
static_assert(sizeof(XYf_STPf_RGBAub) == sizeof(float)*2 + sizeof(float)*3 + sizeof(Color), "sizeof(XYf_STPf_RGBAub) incorrect!");
|
||||
|
||||
size_t getFormatStride(CommonFormat format)
|
||||
{
|
||||
@@ -45,10 +47,14 @@ size_t getFormatStride(CommonFormat format)
|
||||
return sizeof(uint8) * 4;
|
||||
case CommonFormat::XYf_STf:
|
||||
return sizeof(XYf_STf);
|
||||
case CommonFormat::XYf_STPf:
|
||||
return sizeof(XYf_STPf);
|
||||
case CommonFormat::XYf_STf_RGBAub:
|
||||
return sizeof(XYf_STf_RGBAub);
|
||||
case CommonFormat::XYf_STus_RGBAub:
|
||||
return sizeof(XYf_STus_RGBAub);
|
||||
case CommonFormat::XYf_STPf_RGBAub:
|
||||
return sizeof(XYf_STPf_RGBAub);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,9 +69,11 @@ uint32 getFormatFlags(CommonFormat format)
|
||||
case CommonFormat::RGBAub:
|
||||
return ATTRIBFLAG_COLOR;
|
||||
case CommonFormat::XYf_STf:
|
||||
case CommonFormat::XYf_STPf:
|
||||
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
|
||||
case CommonFormat::XYf_STf_RGBAub:
|
||||
case CommonFormat::XYf_STus_RGBAub:
|
||||
case CommonFormat::XYf_STPf_RGBAub:
|
||||
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR;
|
||||
|
||||
}
|
||||
|
||||
@@ -97,8 +97,10 @@ enum class CommonFormat
|
||||
XYf,
|
||||
RGBAub,
|
||||
XYf_STf,
|
||||
XYf_STPf,
|
||||
XYf_STf_RGBAub,
|
||||
XYf_STus_RGBAub,
|
||||
XYf_STPf_RGBAub,
|
||||
};
|
||||
|
||||
struct XYf_STf
|
||||
@@ -107,6 +109,12 @@ struct XYf_STf
|
||||
float s, t;
|
||||
};
|
||||
|
||||
struct XYf_STPf
|
||||
{
|
||||
float x, y;
|
||||
float s, t, p;
|
||||
};
|
||||
|
||||
struct XYf_STf_RGBAub
|
||||
{
|
||||
float x, y;
|
||||
@@ -121,6 +129,13 @@ struct XYf_STus_RGBAub
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct XYf_STPf_RGBAub
|
||||
{
|
||||
float x, y;
|
||||
float s, t, p;
|
||||
Color color;
|
||||
};
|
||||
|
||||
size_t getFormatStride(CommonFormat format);
|
||||
uint32 getFormatFlags(CommonFormat format);
|
||||
size_t getIndexDataSize(IndexDataType type);
|
||||
|
||||
@@ -828,6 +828,7 @@ int w_newQuad(lua_State *L)
|
||||
|
||||
double sw = 0.0f;
|
||||
double sh = 0.0f;
|
||||
int layer = 0;
|
||||
|
||||
if (luax_istype(L, 5, Texture::type))
|
||||
{
|
||||
@@ -835,6 +836,19 @@ int w_newQuad(lua_State *L)
|
||||
sw = texture->getWidth();
|
||||
sh = texture->getHeight();
|
||||
}
|
||||
else if (luax_istype(L, 6, Texture::type))
|
||||
{
|
||||
layer = (int) luaL_checknumber(L, 5) - 1;
|
||||
Texture *texture = luax_checktexture(L, 6);
|
||||
sw = texture->getWidth();
|
||||
sh = texture->getHeight();
|
||||
}
|
||||
else if (!lua_isnoneornil(L, 7))
|
||||
{
|
||||
layer = (int) luaL_checknumber(L, 5) - 1;
|
||||
sw = luaL_checknumber(L, 6);
|
||||
sh = luaL_checknumber(L, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
sw = luaL_checknumber(L, 5);
|
||||
@@ -842,6 +856,8 @@ int w_newQuad(lua_State *L)
|
||||
}
|
||||
|
||||
Quad *quad = instance()->newQuad(v, sw, sh);
|
||||
quad->setLayer(layer);
|
||||
|
||||
luax_pushtype(L, quad);
|
||||
quad->release();
|
||||
return 1;
|
||||
@@ -1761,19 +1777,25 @@ int w_setDefaultShaderCode(lua_State *L)
|
||||
lua_getfield(L, -1, "vertex");
|
||||
lua_getfield(L, -2, "pixel");
|
||||
lua_getfield(L, -3, "videopixel");
|
||||
lua_getfield(L, -4, "arraypixel");
|
||||
|
||||
Shader::ShaderSource code;
|
||||
code.vertex = luax_checkstring(L, -3);
|
||||
code.pixel = luax_checkstring(L, -2);
|
||||
code.vertex = luax_checkstring(L, -4);
|
||||
code.pixel = luax_checkstring(L, -3);
|
||||
|
||||
Shader::ShaderSource videocode;
|
||||
videocode.vertex = luax_checkstring(L, -3);
|
||||
videocode.pixel = luax_checkstring(L, -1);
|
||||
videocode.vertex = luax_checkstring(L, -4);
|
||||
videocode.pixel = luax_checkstring(L, -2);
|
||||
|
||||
lua_pop(L, 4);
|
||||
Shader::ShaderSource arraycode;
|
||||
arraycode.vertex = luax_checkstring(L, -4);
|
||||
arraycode.pixel = luax_checkstring(L, -1);
|
||||
|
||||
Graphics::defaultShaderCode[lang][i] = code;
|
||||
Graphics::defaultVideoShaderCode[lang][i] = videocode;
|
||||
lua_pop(L, 5);
|
||||
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_DEFAULT][lang][i] = code;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_VIDEO][lang][i] = videocode;
|
||||
Graphics::defaultShaderCode[Shader::STANDARD_ARRAY][lang][i] = arraycode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1927,37 +1949,48 @@ int w_draw(lua_State *L)
|
||||
startidx = 2;
|
||||
}
|
||||
|
||||
if (luax_istype(L, startidx, math::Transform::type))
|
||||
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
|
||||
{
|
||||
math::Transform *tf = luax_totype<math::Transform>(L, startidx);
|
||||
luax_catchexcept(L, [&]() {
|
||||
if (texture && quad)
|
||||
instance()->draw(texture, quad, tf->getMatrix());
|
||||
else
|
||||
instance()->draw(drawable, tf->getMatrix());
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (float) luaL_optnumber(L, startidx + 0, 0.0);
|
||||
float y = (float) luaL_optnumber(L, startidx + 1, 0.0);
|
||||
float a = (float) luaL_optnumber(L, startidx + 2, 0.0);
|
||||
float sx = (float) luaL_optnumber(L, startidx + 3, 1.0);
|
||||
float sy = (float) luaL_optnumber(L, startidx + 4, sx);
|
||||
float ox = (float) luaL_optnumber(L, startidx + 5, 0.0);
|
||||
float oy = (float) luaL_optnumber(L, startidx + 6, 0.0);
|
||||
float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
|
||||
float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
|
||||
|
||||
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
luax_catchexcept(L, [&]()
|
||||
{
|
||||
if (texture && quad)
|
||||
instance()->draw(texture, quad, m);
|
||||
else if (drawable)
|
||||
else
|
||||
instance()->draw(drawable, m);
|
||||
});
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_drawLayer(lua_State *L)
|
||||
{
|
||||
Texture *texture = luax_checktexture(L, 1);
|
||||
Quad *quad = nullptr;
|
||||
int layer = (int) luaL_checknumber(L, 2) - 1;
|
||||
int startidx = 3;
|
||||
|
||||
if (luax_istype(L, startidx, Quad::type))
|
||||
{
|
||||
texture = luax_checktexture(L, 1);
|
||||
quad = luax_totype<Quad>(L, startidx);
|
||||
startidx++;
|
||||
}
|
||||
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
|
||||
{
|
||||
return luax_typerror(L, startidx, "Quad");
|
||||
}
|
||||
|
||||
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
|
||||
{
|
||||
luax_catchexcept(L, [&]()
|
||||
{
|
||||
if (quad)
|
||||
instance()->drawLayer(texture, layer, quad, m);
|
||||
else
|
||||
instance()->drawLayer(texture, layer, m);
|
||||
});
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1967,27 +2000,10 @@ int w_drawInstanced(lua_State *L)
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
int instancecount = (int) luaL_checkinteger(L, 2);
|
||||
|
||||
if (luax_istype(L, 3, math::Transform::type))
|
||||
luax_checkstandardtransform(L, 3, [&](const Matrix4 &m)
|
||||
{
|
||||
math::Transform *tf = luax_totype<math::Transform>(L, 3);
|
||||
luax_catchexcept(L, [&]() { instance()->drawInstanced(t, tf->getMatrix(), instancecount); });
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (float) luaL_optnumber(L, 3, 0.0);
|
||||
float y = (float) luaL_optnumber(L, 4, 0.0);
|
||||
float a = (float) luaL_optnumber(L, 5, 0.0);
|
||||
float sx = (float) luaL_optnumber(L, 6, 1.0);
|
||||
float sy = (float) luaL_optnumber(L, 7, sx);
|
||||
float ox = (float) luaL_optnumber(L, 8, 0.0);
|
||||
float oy = (float) luaL_optnumber(L, 9, 0.0);
|
||||
float kx = (float) luaL_optnumber(L, 10, 0.0);
|
||||
float ky = (float) luaL_optnumber(L, 11, 0.0);
|
||||
|
||||
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
luax_catchexcept(L, [&]() { instance()->drawInstanced(t, m, instancecount); });
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1997,27 +2013,11 @@ int w_print(lua_State *L)
|
||||
std::vector<Font::ColoredString> str;
|
||||
luax_checkcoloredstring(L, 1, str);
|
||||
|
||||
if (luax_istype(L, 2, math::Transform::type))
|
||||
luax_checkstandardtransform(L, 2, [&](const Matrix4 &m)
|
||||
{
|
||||
math::Transform *tf = luax_totype<math::Transform>(L, 2);
|
||||
luax_catchexcept(L, [&](){ instance()->print(str, tf->getMatrix()); });
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (float)luaL_optnumber(L, 2, 0.0);
|
||||
float y = (float)luaL_optnumber(L, 3, 0.0);
|
||||
float angle = (float)luaL_optnumber(L, 4, 0.0f);
|
||||
float sx = (float)luaL_optnumber(L, 5, 1.0f);
|
||||
float sy = (float)luaL_optnumber(L, 6, sx);
|
||||
float ox = (float)luaL_optnumber(L, 7, 0.0f);
|
||||
float oy = (float)luaL_optnumber(L, 8, 0.0f);
|
||||
float kx = (float)luaL_optnumber(L, 9, 0.0f);
|
||||
float ky = (float)luaL_optnumber(L, 10, 0.0f);
|
||||
|
||||
Matrix4 m(x, y, angle, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
luax_catchexcept(L, [&](){ instance()->print(str, m); });
|
||||
}
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2519,6 +2519,7 @@ static const luaL_Reg functions[] =
|
||||
{ "captureScreenshot", w_captureScreenshot },
|
||||
|
||||
{ "draw", w_draw },
|
||||
{ "drawLayer", w_drawLayer },
|
||||
{ "drawInstanced", w_drawInstanced },
|
||||
|
||||
{ "print", w_print },
|
||||
|
||||
@@ -412,6 +412,11 @@ vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
|
||||
videopixel = [[
|
||||
vec4 effect(vec4 vcolor, Image tex, vec2 texcoord, vec2 pixcoord) {
|
||||
return VideoTexel(texcoord) * vcolor;
|
||||
}]],
|
||||
arraypixel = [[
|
||||
uniform ArrayImage MainTex;
|
||||
void effect() {
|
||||
love_PixelColor = Texel(MainTex, VaryingTexCoord.xyz) * VaryingColor;
|
||||
}]],
|
||||
}
|
||||
|
||||
@@ -432,6 +437,7 @@ for lang, info in pairs(langs) do
|
||||
vertex = createShaderStageCode("VERTEX", defaultcode.vertex, info.target, info.gles, false, gammacorrect),
|
||||
pixel = createShaderStageCode("PIXEL", defaultcode.pixel, info.target, info.gles, false, gammacorrect, false),
|
||||
videopixel = createShaderStageCode("PIXEL", defaultcode.videopixel, info.target, info.gles, false, gammacorrect, false),
|
||||
arraypixel = createShaderStageCode("PIXEL", defaultcode.arraypixel, info.target, info.gles, false, gammacorrect, true),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -74,11 +74,28 @@ int w_Quad_getTextureDimensions(lua_State *L)
|
||||
return 2;
|
||||
}
|
||||
|
||||
int w_Quad_setLayer(lua_State *L)
|
||||
{
|
||||
Quad *quad = luax_checkquad(L, 1);
|
||||
int layer = (int) luaL_checknumber(L, 2) - 1;
|
||||
quad->setLayer(layer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_Quad_getLayer(lua_State *L)
|
||||
{
|
||||
Quad *quad = luax_checkquad(L, 1);
|
||||
lua_pushnumber(L, quad->getLayer() + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg w_Quad_functions[] =
|
||||
{
|
||||
{ "setViewport", w_Quad_setViewport },
|
||||
{ "getViewport", w_Quad_getViewport },
|
||||
{ "getTextureDimensions", w_Quad_getTextureDimensions },
|
||||
{ "setLayer", w_Quad_setLayer },
|
||||
{ "getLayer", w_Quad_getLayer },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "Image.h"
|
||||
#include "Canvas.h"
|
||||
#include "wrap_Texture.h"
|
||||
#include "math/wrap_Transform.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
@@ -47,37 +46,44 @@ static inline int w_SpriteBatch_add_or_set(lua_State *L, SpriteBatch *t, int sta
|
||||
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
|
||||
return luax_typerror(L, startidx, "Quad");
|
||||
|
||||
if (luax_istype(L, startidx, math::Transform::type))
|
||||
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
|
||||
{
|
||||
math::Transform *tf = luax_totype<math::Transform>(L, startidx);
|
||||
luax_catchexcept(L, [&]() {
|
||||
luax_catchexcept(L, [&]()
|
||||
{
|
||||
if (quad)
|
||||
index = t->addq(quad, tf->getMatrix(), index);
|
||||
else
|
||||
index = t->add(tf->getMatrix(), index);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (float) luaL_optnumber(L, startidx + 0, 0.0);
|
||||
float y = (float) luaL_optnumber(L, startidx + 1, 0.0);
|
||||
float a = (float) luaL_optnumber(L, startidx + 2, 0.0);
|
||||
float sx = (float) luaL_optnumber(L, startidx + 3, 1.0);
|
||||
float sy = (float) luaL_optnumber(L, startidx + 4, sx);
|
||||
float ox = (float) luaL_optnumber(L, startidx + 5, 0.0);
|
||||
float oy = (float) luaL_optnumber(L, startidx + 6, 0.0);
|
||||
float kx = (float) luaL_optnumber(L, startidx + 7, 0.0);
|
||||
float ky = (float) luaL_optnumber(L, startidx + 8, 0.0);
|
||||
|
||||
Matrix4 m(x, y, a, sx, sy, ox, oy, kx, ky);
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
if (quad)
|
||||
index = t->addq(quad, m, index);
|
||||
index = t->add(quad, m, index);
|
||||
else
|
||||
index = t->add(m, index);
|
||||
});
|
||||
});
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static int w_SpriteBatch_addLayer_or_setLayer(lua_State *L, SpriteBatch *t, int startidx, int index)
|
||||
{
|
||||
Quad *quad = nullptr;
|
||||
int layer = (int) luaL_checknumber(L, startidx) - 1;
|
||||
startidx++;
|
||||
|
||||
if (luax_istype(L, startidx, Quad::type))
|
||||
{
|
||||
quad = luax_totype<Quad>(L, startidx);
|
||||
startidx++;
|
||||
}
|
||||
else if (lua_isnil(L, startidx) && !lua_isnoneornil(L, startidx + 1))
|
||||
return luax_typerror(L, startidx, "Quad");
|
||||
|
||||
luax_checkstandardtransform(L, startidx, [&](const Matrix4 &m)
|
||||
{
|
||||
luax_catchexcept(L, [&]()
|
||||
{
|
||||
if (quad)
|
||||
index = t->addLayer(layer, quad, m, index);
|
||||
else
|
||||
index = t->addLayer(layer, m, index);
|
||||
});
|
||||
});
|
||||
|
||||
return index;
|
||||
}
|
||||
@@ -102,6 +108,26 @@ int w_SpriteBatch_set(lua_State *L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_SpriteBatch_addLayer(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
|
||||
int index = w_SpriteBatch_addLayer_or_setLayer(L, t, 2, -1);
|
||||
lua_pushinteger(L, index + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int w_SpriteBatch_setLayer(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
int index = (int) luaL_checknumber(L, 2) - 1;
|
||||
|
||||
w_SpriteBatch_addLayer_or_setLayer(L, t, 3, index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int w_SpriteBatch_clear(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
@@ -178,16 +204,17 @@ int w_SpriteBatch_setColor(lua_State *L)
|
||||
int w_SpriteBatch_getColor(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
const Color *color = t->getColor();
|
||||
bool active = false;
|
||||
const Color &color = t->getColor(active);
|
||||
|
||||
// getColor returns null if no color is set.
|
||||
if (!color)
|
||||
if (!active)
|
||||
return 0;
|
||||
|
||||
lua_pushnumber(L, (lua_Number) color->r / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color->g / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color->b / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color->a / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color.r / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color.g / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color.b / 255.0);
|
||||
lua_pushnumber(L, (lua_Number) color.a / 255.0);
|
||||
|
||||
return 4;
|
||||
}
|
||||
@@ -250,6 +277,8 @@ static const luaL_Reg w_SpriteBatch_functions[] =
|
||||
{
|
||||
{ "add", w_SpriteBatch_add },
|
||||
{ "set", w_SpriteBatch_set },
|
||||
{ "addLayer", w_SpriteBatch_addLayer },
|
||||
{ "setLayer", w_SpriteBatch_setLayer },
|
||||
{ "clear", w_SpriteBatch_clear },
|
||||
{ "flush", w_SpriteBatch_flush },
|
||||
{ "setTexture", w_SpriteBatch_setTexture },
|
||||
|
||||
@@ -22,12 +22,36 @@
|
||||
|
||||
#include "common/runtime.h"
|
||||
#include "SpriteBatch.h"
|
||||
#include "math/wrap_Transform.h"
|
||||
|
||||
namespace love
|
||||
{
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
static void luax_checkstandardtransform(lua_State *L, int idx, const T &func)
|
||||
{
|
||||
if (luax_istype(L, idx, math::Transform::type))
|
||||
{
|
||||
math::Transform *tf = luax_totype<math::Transform>(L, idx);
|
||||
func(tf->getMatrix());
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (float) luaL_optnumber(L, idx + 0, 0.0);
|
||||
float y = (float) luaL_optnumber(L, idx + 1, 0.0);
|
||||
float a = (float) luaL_optnumber(L, idx + 2, 0.0);
|
||||
float sx = (float) luaL_optnumber(L, idx + 3, 1.0);
|
||||
float sy = (float) luaL_optnumber(L, idx + 4, sx);
|
||||
float ox = (float) luaL_optnumber(L, idx + 5, 0.0);
|
||||
float oy = (float) luaL_optnumber(L, idx + 6, 0.0);
|
||||
float kx = (float) luaL_optnumber(L, idx + 7, 0.0);
|
||||
float ky = (float) luaL_optnumber(L, idx + 8, 0.0);
|
||||
func(Matrix4(x, y, a, sx, sy, ox, oy, kx, ky));
|
||||
}
|
||||
}
|
||||
|
||||
SpriteBatch *luax_checkspritebatch(lua_State *L, int idx);
|
||||
extern "C" int luaopen_spritebatch(lua_State *L);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user