Auto-batched draws (except for love.graphics.print, for now) are affected by 3D transforms.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-05-17 22:03:09 -03:00
parent 955fb9b60c
commit 7694edfd52
12 changed files with 174 additions and 79 deletions
+17 -17
View File
@@ -616,16 +616,6 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
if (state.vertexCount == 0 && Shader::current != nullptr && req.texture != nullptr)
Shader::current->checkMainTexture(req.texture);
if (!getTransform().isAffine2DTransform())
{
for (CommonFormat fmt : req.formats)
{
int components = getFormatPositionComponents(fmt);
if (components > 0 && components < 3)
throw love::Exception("Only affine 2D transforms are supported with auto-batched draws.");
}
}
bool shouldflush = false;
bool shouldresize = false;
@@ -811,16 +801,21 @@ void Graphics::printf(const std::vector<Font::ColoredString> &str, Font *font, f
void Graphics::points(const float *coords, const Colorf *colors, size_t numpoints)
{
const Matrix4 &t = getTransform();
bool is2D = t.isAffine2DTransform();
StreamDrawRequest req;
req.primitiveMode = vertex::PrimitiveMode::POINTS;
req.formats[0] = vertex::CommonFormat::XYf;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = vertex::CommonFormat::RGBAub;
req.vertexCount = (int) numpoints;
StreamVertexData data = requestStreamDraw(req);
const Matrix4 &t = getTransform();
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
if (is2D)
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
else
t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
Color *colordata = (Color *) data.stream[1];
@@ -1095,16 +1090,21 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
}
else
{
const Matrix4 &t = getTransform();
bool is2D = t.isAffine2DTransform();
StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = vertex::CommonFormat::RGBAub;
req.indexMode = vertex::TriangleIndexMode::FAN;
req.vertexCount = (int)count/2 - 1;
StreamVertexData data = requestStreamDraw(req);
const Matrix4 &t = getTransform();
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
if (is2D)
t.transformXY((Vector2 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
else
t.transformXY0((Vector3 *) data.stream[0], (const Vector2 *) coords, req.vertexCount);
Color c = toColor(getColor());
Color *colordata = (Color *) data.stream[1];
+10 -5
View File
@@ -1057,7 +1057,9 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
gfx->flushStreamDraws();
const vertex::XYf_STf *textureVerts = texture->getQuad()->getVertices();
const Vector2 *positions = texture->getQuad()->getVertexPositions();
const Vector2 *texcoords = texture->getQuad()->getVertexTexCoords();
Vertex *pVerts = (Vertex *) buffer->map();
Particle *p = pHead;
@@ -1069,11 +1071,14 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
while (p)
{
if (useQuads)
textureVerts = quads[p->quadIndex]->getVertices();
{
positions = quads[p->quadIndex]->getVertexPositions();
texcoords = quads[p->quadIndex]->getVertexTexCoords();
}
// particle vertices are image vertices transformed by particle info
t.setTransformation(p->position.x, p->position.y, p->angle, p->size, p->size, offset.x, offset.y, 0.0f, 0.0f);
t.transformXY(pVerts, textureVerts, 4);
t.transformXY(pVerts, positions, 4);
// Particle colors are stored as floats (0-1) but vertex colors are
// unsigned bytes (0-255).
@@ -1082,8 +1087,8 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
// set the texture coordinate and color data for particle vertices
for (int v = 0; v < 4; v++)
{
pVerts[v].s = textureVerts[v].s;
pVerts[v].t = textureVerts[v].t;
pVerts[v].s = texcoords[v].x;
pVerts[v].t = texcoords[v].y;
pVerts[v].color = c;
}
+8 -3
View File
@@ -371,16 +371,21 @@ void Polyline::draw(love::graphics::Graphics *gfx)
if (overdraw)
total_vertex_count = (int) (overdraw_vertex_start + overdraw_vertex_count);
const Matrix4 &t = gfx->getTransform();
bool is2D = t.isAffine2DTransform();
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = vertex::CommonFormat::RGBAub;
req.indexMode = triangle_mode;
req.vertexCount = total_vertex_count;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
const Matrix4 &t = gfx->getTransform();
t.transformXY((Vector2 *) data.stream[0], vertices, total_vertex_count);
if (is2D)
t.transformXY((Vector2 *) data.stream[0], vertices, total_vertex_count);
else
t.transformXY0((Vector3 *) data.stream[0], vertices, total_vertex_count);
Color curcolor = toColor(gfx->getColor());
Color *colordata = (Color *) data.stream[1];
+8 -21
View File
@@ -53,23 +53,15 @@ void Quad::refresh(const Quad::Viewport &v, double sw, double sh)
// 0---2
// | / |
// 1---3
vertices[0].x = 0.0f;
vertices[0].y = 0.0f;
vertices[1].x = 0.0f;
vertices[1].y = (float) v.h;
vertices[2].x = (float) v.w;
vertices[2].y = 0.0f;
vertices[3].x = (float) v.w;
vertices[3].y = (float) v.h;
vertexPositions[0] = Vector2(0.0f, 0.0f);
vertexPositions[1] = Vector2(0.0f, (float) v.h);
vertexPositions[2] = Vector2((float) v.w, 0.0f);
vertexPositions[3] = Vector2((float) v.w, (float) v.h);
vertices[0].s = (float) (v.x / sw);
vertices[0].t = (float) (v.y / sh);
vertices[1].s = (float) (v.x / sw);
vertices[1].t = (float) ((v.y + v.h) / sh);
vertices[2].s = (float) ((v.x + v.w) / sw);
vertices[2].t = (float) (v.y / sh);
vertices[3].s = (float) ((v.x + v.w) / sw);
vertices[3].t = (float) ((v.y + v.h) / sh);
vertexTexCoords[0] = Vector2((float) (v.x / sw), (float) (v.y / sh));
vertexTexCoords[1] = Vector2((float) (v.x / sw), (float) ((v.y + v.h) / sh));
vertexTexCoords[2] = Vector2((float) ((v.x + v.w) / sw), (float) (v.y / sh));
vertexTexCoords[3] = Vector2((float) ((v.x + v.w) / sw), (float) ((v.y + v.h) / sh));
}
void Quad::setViewport(const Quad::Viewport &v)
@@ -92,11 +84,6 @@ double Quad::getTextureHeight() const
return sh;
}
const vertex::XYf_STf *Quad::getVertices() const
{
return vertices;
}
void Quad::setLayer(int layer)
{
arrayLayer = layer;
+5 -3
View File
@@ -24,7 +24,7 @@
// LOVE
#include "common/Object.h"
#include "common/math.h"
#include "vertex.h"
#include "common/Vector.h"
namespace love
{
@@ -53,14 +53,16 @@ public:
double getTextureWidth() const;
double getTextureHeight() const;
const vertex::XYf_STf *getVertices() const;
const Vector2 *getVertexPositions() const { return vertexPositions; }
const Vector2 *getVertexTexCoords() const { return vertexTexCoords; }
void setLayer(int layer);
int getLayer() const;
private:
vertex::XYf_STf vertices[4];
Vector2 vertexPositions[4];
Vector2 vertexTexCoords[4];
int arrayLayer;
+10 -8
View File
@@ -91,18 +91,19 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
if (index == -1 && next >= size)
setBufferSize(size * 2);
const XYf_STf *quadverts = quad->getVertices();
const Vector2 *quadpositions = quad->getVertexPositions();
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// 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.transformXY(verts, quadverts, 4);
m.transformXY(verts, quadpositions, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].s = quadtexcoords[i].x;
verts[i].t = quadtexcoords[i].y;
verts[i].color = color;
}
@@ -136,18 +137,19 @@ int SpriteBatch::addLayer(int layer, Quad *quad, const Matrix4 &m, int index)
if (index == -1 && next >= size)
setBufferSize(size * 2);
const XYf_STf *quadverts = quad->getVertices();
const Vector2 *quadpositions = quad->getVertexPositions();
const Vector2 *quadtexcoords = quad->getVertexTexCoords();
// 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.transformXY(verts, quadverts, 4);
m.transformXY(verts, quadpositions, 4);
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].s = quadtexcoords[i].x;
verts[i].t = quadtexcoords[i].y;
verts[i].p = (float) layer;
verts[i].color = color;
}
+33 -17
View File
@@ -122,25 +122,33 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform)
Color c = toColor(gfx->getColor());
const Matrix4 &tm = gfx->getTransform();
bool is2D = tm.isAffine2DTransform();
Matrix4 t(tm, localTransform);
Graphics::StreamDrawRequest req;
req.formats[0] = CommonFormat::XYf_STf_RGBAub;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = CommonFormat::STf_RGBAub;
req.indexMode = TriangleIndexMode::QUADS;
req.vertexCount = 4;
req.texture = this;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
XYf_STf_RGBAub *verts = (XYf_STf_RGBAub *) data.stream[0];
const XYf_STf *quadverts = q->getVertices();
if (is2D)
t.transformXY((Vector2 *) data.stream[0], q->getVertexPositions(), 4);
else
t.transformXY0((Vector3 *) data.stream[0], q->getVertexPositions(), 4);
Matrix4 t(gfx->getTransform(), localTransform);
t.transformXY(verts, quadverts, 4);
const Vector2 *texcoords = q->getVertexTexCoords();
vertex::STf_RGBAub *vertexdata = (vertex::STf_RGBAub *) data.stream[1];
for (int i = 0; i < 4; i++)
{
verts[i].s = quadverts[i].s;
verts[i].t = quadverts[i].t;
verts[i].color = c;
vertexdata[i].s = texcoords[i].x;
vertexdata[i].t = texcoords[i].y;
vertexdata[i].color = c;
}
}
@@ -164,26 +172,34 @@ void Texture::drawLayer(Graphics *gfx, int layer, Quad *q, const Matrix4 &m)
Color c = toColor(gfx->getColor());
const Matrix4 &tm = gfx->getTransform();
bool is2D = tm.isAffine2DTransform();
Matrix4 t(tm, m);
Graphics::StreamDrawRequest req;
req.formats[0] = CommonFormat::XYf_STPf_RGBAub;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = CommonFormat::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();
if (is2D)
t.transformXY((Vector2 *) data.stream[0], q->getVertexPositions(), 4);
else
t.transformXY0((Vector3 *) data.stream[0], q->getVertexPositions(), 4);
Matrix4 t(gfx->getTransform(), m);
t.transformXY(verts, quadverts, 4);
const Vector2 *texcoords = q->getVertexTexCoords();
vertex::STPf_RGBAub *vertexdata = (vertex::STPf_RGBAub *) data.stream[1];
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;
vertexdata[i].s = texcoords[i].x;
vertexdata[i].t = texcoords[i].y;
vertexdata[i].p = (float) layer;
vertexdata[i].color = c;
}
}
+13 -4
View File
@@ -122,16 +122,25 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
if (Shader::current != nullptr)
Shader::current->setVideoTextures(images[0], images[1], images[2]);
const Matrix4 &tm = gfx->getTransform();
bool is2D = tm.isAffine2DTransform();
Matrix4 t(tm, m);
Graphics::StreamDrawRequest req;
req.formats[0] = vertex::CommonFormat::XYf_STf_RGBAub;
req.formats[0] = vertex::getSinglePositionFormat(is2D);
req.formats[1] = vertex::CommonFormat::STf_RGBAub;
req.indexMode = vertex::TriangleIndexMode::QUADS;
req.vertexCount = 4;
Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
Vertex *verts = (Vertex *) data.stream[0];
Matrix4 t(gfx->getTransform(), m);
t.transformXY(verts, vertices, 4);
if (is2D)
t.transformXY((Vector2 *) data.stream[0], vertices, 4);
else
t.transformXY0((Vector3 *) data.stream[0], vertices, 4);
vertex::STf_RGBAub *verts = (vertex::STf_RGBAub *) data.stream[1];
Color c = toColor(gfx->getColor());
+11
View File
@@ -653,9 +653,20 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
case CommonFormat::XYf:
glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::XYZf:
glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::RGBAub:
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset));
break;
case CommonFormat::STf_RGBAub:
glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STf_RGBAub, color.r)));
break;
case CommonFormat::STPf_RGBAub:
glVertexAttribPointer(ATTRIB_TEXCOORD, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, s)));
glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset + offsetof(STPf_RGBAub, color.r)));
break;
case CommonFormat::XYf_STf:
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)));
+16 -1
View File
@@ -29,6 +29,8 @@ namespace vertex
{
static_assert(sizeof(Color) == 4, "sizeof(Color) incorrect!");
static_assert(sizeof(STf_RGBAub) == sizeof(float)*2 + sizeof(Color), "sizeof(STf_RGBAub) incorrect!");
static_assert(sizeof(STPf_RGBAub) == sizeof(float)*3 + sizeof(Color), "sizeof(STPf_RGBAub) 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!");
@@ -43,8 +45,14 @@ size_t getFormatStride(CommonFormat format)
return 0;
case CommonFormat::XYf:
return sizeof(float) * 2;
case CommonFormat::XYZf:
return sizeof(float) * 3;
case CommonFormat::RGBAub:
return sizeof(uint8) * 4;
case CommonFormat::STf_RGBAub:
return sizeof(STf_RGBAub);
case CommonFormat::STPf_RGBAub:
return sizeof(STPf_RGBAub);
case CommonFormat::XYf_STf:
return sizeof(XYf_STf);
case CommonFormat::XYf_STPf:
@@ -65,9 +73,13 @@ uint32 getFormatFlags(CommonFormat format)
case CommonFormat::NONE:
return 0;
case CommonFormat::XYf:
case CommonFormat::XYZf:
return ATTRIBFLAG_POS;
case CommonFormat::RGBAub:
return ATTRIBFLAG_COLOR;
case CommonFormat::STf_RGBAub:
case CommonFormat::STPf_RGBAub:
return ATTRIBFLAG_TEXCOORD | ATTRIB_COLOR;
case CommonFormat::XYf_STf:
case CommonFormat::XYf_STPf:
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
@@ -75,7 +87,6 @@ uint32 getFormatFlags(CommonFormat format)
case CommonFormat::XYf_STus_RGBAub:
case CommonFormat::XYf_STPf_RGBAub:
return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR;
}
}
@@ -85,6 +96,8 @@ int getFormatPositionComponents(CommonFormat format)
{
case CommonFormat::NONE:
case CommonFormat::RGBAub:
case CommonFormat::STf_RGBAub:
case CommonFormat::STPf_RGBAub:
return 0;
case CommonFormat::XYf:
case CommonFormat::XYf_STf:
@@ -93,6 +106,8 @@ int getFormatPositionComponents(CommonFormat format)
case CommonFormat::XYf_STus_RGBAub:
case CommonFormat::XYf_STPf_RGBAub:
return 2;
case CommonFormat::XYZf:
return 3;
}
}
+20
View File
@@ -95,7 +95,10 @@ enum class CommonFormat
{
NONE,
XYf,
XYZf,
RGBAub,
STf_RGBAub,
STPf_RGBAub,
XYf_STf,
XYf_STPf,
XYf_STf_RGBAub,
@@ -103,6 +106,18 @@ enum class CommonFormat
XYf_STPf_RGBAub,
};
struct STf_RGBAub
{
float s, t;
Color color;
};
struct STPf_RGBAub
{
float s, t, p;
Color color;
};
struct XYf_STf
{
float x, y;
@@ -142,6 +157,11 @@ uint32 getFormatFlags(CommonFormat format);
int getFormatPositionComponents(CommonFormat format);
inline CommonFormat getSinglePositionFormat(bool is2D)
{
return is2D ? CommonFormat::XYf : CommonFormat::XYZf;
}
size_t getIndexDataSize(IndexDataType type);
IndexDataType getIndexDataTypeFromMax(size_t maxvalue);