Browse Source

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

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
7694edfd52

+ 23 - 0
src/common/Matrix.h

@@ -191,6 +191,13 @@ public:
 	template <typename Vdst, typename Vsrc>
 	template <typename Vdst, typename Vsrc>
 	void transformXY(Vdst *dst, const Vsrc *src, int size) const;
 	void transformXY(Vdst *dst, const Vsrc *src, int size) const;
 
 
+	/**
+	 * Transforms an array of 2-component vertices by this Matrix, and stores
+	 * them in an array of 3-component vertices.
+	 **/
+	template <typename Vdst, typename Vsrc>
+	void transformXY0(Vdst *dst, const Vsrc *src, int size) const;
+
 	/**
 	/**
 	 * Transforms an array of 3-component vertices by this Matrix. The source
 	 * Transforms an array of 3-component vertices by this Matrix. The source
 	 * and destination arrays may be the same.
 	 * and destination arrays may be the same.
@@ -320,6 +327,22 @@ void Matrix4::transformXY(Vdst *dst, const Vsrc *src, int size) const
 	}
 	}
 }
 }
 
 
+template <typename Vdst, typename Vsrc>
+void Matrix4::transformXY0(Vdst *dst, const Vsrc *src, int size) const
+{
+	for (int i = 0; i < size; i++)
+	{
+		// Store in temp variables in case src = dst
+		float x = (e[0]*src[i].x) + (e[4]*src[i].y) + (0) + (e[12]);
+		float y = (e[1]*src[i].x) + (e[5]*src[i].y) + (0) + (e[13]);
+		float z = (e[2]*src[i].x) + (e[6]*src[i].y) + (0) + (e[14]);
+
+		dst[i].x = x;
+		dst[i].y = y;
+		dst[i].z = z;
+	}
+}
+
 //                 | x |
 //                 | x |
 //                 | y |
 //                 | y |
 //                 | z |
 //                 | z |

+ 17 - 17
src/modules/graphics/Graphics.cpp

@@ -616,16 +616,6 @@ Graphics::StreamVertexData Graphics::requestStreamDraw(const StreamDrawRequest &
 	if (state.vertexCount == 0 && Shader::current != nullptr && req.texture != nullptr)
 	if (state.vertexCount == 0 && Shader::current != nullptr && req.texture != nullptr)
 		Shader::current->checkMainTexture(req.texture);
 		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 shouldflush = false;
 	bool shouldresize = 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)
 void Graphics::points(const float *coords, const Colorf *colors, size_t numpoints)
 {
 {
+	const Matrix4 &t = getTransform();
+	bool is2D = t.isAffine2DTransform();
+
 	StreamDrawRequest req;
 	StreamDrawRequest req;
 	req.primitiveMode = vertex::PrimitiveMode::POINTS;
 	req.primitiveMode = vertex::PrimitiveMode::POINTS;
-	req.formats[0] = vertex::CommonFormat::XYf;
+	req.formats[0] = vertex::getSinglePositionFormat(is2D);
 	req.formats[1] = vertex::CommonFormat::RGBAub;
 	req.formats[1] = vertex::CommonFormat::RGBAub;
 	req.vertexCount = (int) numpoints;
 	req.vertexCount = (int) numpoints;
 
 
 	StreamVertexData data = requestStreamDraw(req);
 	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];
 	Color *colordata = (Color *) data.stream[1];
 
 
@@ -1095,16 +1090,21 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
 	}
 	}
 	else
 	else
 	{
 	{
+		const Matrix4 &t = getTransform();
+		bool is2D = t.isAffine2DTransform();
+
 		StreamDrawRequest req;
 		StreamDrawRequest req;
-		req.formats[0] = vertex::CommonFormat::XYf;
+		req.formats[0] = vertex::getSinglePositionFormat(is2D);
 		req.formats[1] = vertex::CommonFormat::RGBAub;
 		req.formats[1] = vertex::CommonFormat::RGBAub;
 		req.indexMode = vertex::TriangleIndexMode::FAN;
 		req.indexMode = vertex::TriangleIndexMode::FAN;
 		req.vertexCount = (int)count/2 - 1;
 		req.vertexCount = (int)count/2 - 1;
 
 
 		StreamVertexData data = requestStreamDraw(req);
 		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 c = toColor(getColor());
 		Color *colordata = (Color *) data.stream[1];
 		Color *colordata = (Color *) data.stream[1];

+ 10 - 5
src/modules/graphics/ParticleSystem.cpp

@@ -1057,7 +1057,9 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
 
 
 	gfx->flushStreamDraws();
 	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();
 	Vertex *pVerts = (Vertex *) buffer->map();
 	Particle *p = pHead;
 	Particle *p = pHead;
 
 
@@ -1069,11 +1071,14 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
 	while (p)
 	while (p)
 	{
 	{
 		if (useQuads)
 		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
 		// 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.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
 		// Particle colors are stored as floats (0-1) but vertex colors are
 		// unsigned bytes (0-255).
 		// unsigned bytes (0-255).
@@ -1082,8 +1087,8 @@ bool ParticleSystem::prepareDraw(Graphics *gfx)
 		// set the texture coordinate and color data for particle vertices
 		// set the texture coordinate and color data for particle vertices
 		for (int v = 0; v < 4; v++)
 		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;
 			pVerts[v].color = c;
 		}
 		}
 
 

+ 8 - 3
src/modules/graphics/Polyline.cpp

@@ -371,16 +371,21 @@ void Polyline::draw(love::graphics::Graphics *gfx)
 	if (overdraw)
 	if (overdraw)
 		total_vertex_count = (int) (overdraw_vertex_start + overdraw_vertex_count);
 		total_vertex_count = (int) (overdraw_vertex_start + overdraw_vertex_count);
 
 
+	const Matrix4 &t = gfx->getTransform();
+	bool is2D = t.isAffine2DTransform();
+
 	Graphics::StreamDrawRequest req;
 	Graphics::StreamDrawRequest req;
-	req.formats[0] = vertex::CommonFormat::XYf;
+	req.formats[0] = vertex::getSinglePositionFormat(is2D);
 	req.formats[1] = vertex::CommonFormat::RGBAub;
 	req.formats[1] = vertex::CommonFormat::RGBAub;
 	req.indexMode = triangle_mode;
 	req.indexMode = triangle_mode;
 	req.vertexCount = total_vertex_count;
 	req.vertexCount = total_vertex_count;
 
 
 	Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
 	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 curcolor = toColor(gfx->getColor());
 	Color *colordata = (Color *) data.stream[1];
 	Color *colordata = (Color *) data.stream[1];

+ 9 - 22
src/modules/graphics/Quad.cpp

@@ -53,23 +53,15 @@ void Quad::refresh(const Quad::Viewport &v, double sw, double sh)
 	// 0---2
 	// 0---2
 	// | / |
 	// | / |
 	// 1---3
 	// 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;
-
-	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);
+	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);
+
+	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)
 void Quad::setViewport(const Quad::Viewport &v)
@@ -92,11 +84,6 @@ double Quad::getTextureHeight() const
 	return sh;
 	return sh;
 }
 }
 
 
-const vertex::XYf_STf *Quad::getVertices() const
-{
-	return vertices;
-}
-
 void Quad::setLayer(int layer)
 void Quad::setLayer(int layer)
 {
 {
 	arrayLayer = layer;
 	arrayLayer = layer;

+ 5 - 3
src/modules/graphics/Quad.h

@@ -24,7 +24,7 @@
 // LOVE
 // LOVE
 #include "common/Object.h"
 #include "common/Object.h"
 #include "common/math.h"
 #include "common/math.h"
-#include "vertex.h"
+#include "common/Vector.h"
 
 
 namespace love
 namespace love
 {
 {
@@ -53,14 +53,16 @@ public:
 	double getTextureWidth() const;
 	double getTextureWidth() const;
 	double getTextureHeight() 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);
 	void setLayer(int layer);
 	int getLayer() const;
 	int getLayer() const;
 
 
 private:
 private:
 
 
-	vertex::XYf_STf vertices[4];
+	Vector2 vertexPositions[4];
+	Vector2 vertexTexCoords[4];
 
 
 	int arrayLayer;
 	int arrayLayer;
 
 

+ 10 - 8
src/modules/graphics/SpriteBatch.cpp

@@ -91,18 +91,19 @@ int SpriteBatch::add(Quad *quad, const Matrix4 &m, int index /*= -1*/)
 	if (index == -1 && next >= size)
 	if (index == -1 && next >= size)
 		setBufferSize(size * 2);
 		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.)
 	// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
 	size_t offset = (index == -1 ? next : index) * format_stride * 4;
 	size_t offset = (index == -1 ? next : index) * format_stride * 4;
 	auto verts = (XYf_STf_RGBAub *) ((uint8 *) array_buf->map() + offset);
 	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++)
 	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;
 		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)
 	if (index == -1 && next >= size)
 		setBufferSize(size * 2);
 		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.)
 	// Always keep the VBO mapped when adding data (it'll be unmapped on draw.)
 	size_t offset = (index == -1 ? next : index) * format_stride * 4;
 	size_t offset = (index == -1 ? next : index) * format_stride * 4;
 	auto verts = (XYf_STPf_RGBAub *) ((uint8 *) array_buf->map() + offset);
 	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++)
 	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].p = (float) layer;
 		verts[i].color = color;
 		verts[i].color = color;
 	}
 	}

+ 33 - 17
src/modules/graphics/Texture.cpp

@@ -122,25 +122,33 @@ void Texture::draw(Graphics *gfx, Quad *q, const Matrix4 &localTransform)
 
 
 	Color c = toColor(gfx->getColor());
 	Color c = toColor(gfx->getColor());
 
 
+	const Matrix4 &tm = gfx->getTransform();
+	bool is2D = tm.isAffine2DTransform();
+
+	Matrix4 t(tm, localTransform);
+
 	Graphics::StreamDrawRequest req;
 	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.indexMode = TriangleIndexMode::QUADS;
 	req.vertexCount = 4;
 	req.vertexCount = 4;
 	req.texture = this;
 	req.texture = this;
 
 
 	Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
 	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++)
 	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());
 	Color c = toColor(gfx->getColor());
 
 
+	const Matrix4 &tm = gfx->getTransform();
+	bool is2D = tm.isAffine2DTransform();
+
+	Matrix4 t(tm, m);
+
 	Graphics::StreamDrawRequest req;
 	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.indexMode = TriangleIndexMode::QUADS;
 	req.vertexCount = 4;
 	req.vertexCount = 4;
 	req.texture = this;
 	req.texture = this;
 
 
 	Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
 	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++)
 	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
src/modules/graphics/Video.cpp

@@ -122,16 +122,25 @@ void Video::draw(Graphics *gfx, const Matrix4 &m)
 	if (Shader::current != nullptr)
 	if (Shader::current != nullptr)
 		Shader::current->setVideoTextures(images[0], images[1], images[2]);
 		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;
 	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.indexMode = vertex::TriangleIndexMode::QUADS;
 	req.vertexCount = 4;
 	req.vertexCount = 4;
 
 
 	Graphics::StreamVertexData data = gfx->requestStreamDraw(req);
 	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());
 	Color c = toColor(gfx->getColor());
 
 

+ 11 - 0
src/modules/graphics/opengl/OpenGL.cpp

@@ -653,9 +653,20 @@ void OpenGL::setVertexPointers(vertex::CommonFormat format, size_t stride, size_
 	case CommonFormat::XYf:
 	case CommonFormat::XYf:
 		glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
 		glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
 		break;
 		break;
+	case CommonFormat::XYZf:
+		glVertexAttribPointer(ATTRIB_POS, 3, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset));
+		break;
 	case CommonFormat::RGBAub:
 	case CommonFormat::RGBAub:
 		glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset));
 		glVertexAttribPointer(ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, BUFFER_OFFSET(offset));
 		break;
 		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:
 	case CommonFormat::XYf_STf:
 		glVertexAttribPointer(ATTRIB_POS, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, x)));
 		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)));
 		glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, BUFFER_OFFSET(offset + offsetof(XYf_STf, s)));

+ 16 - 1
src/modules/graphics/vertex.cpp

@@ -29,6 +29,8 @@ namespace vertex
 {
 {
 
 
 static_assert(sizeof(Color) == 4, "sizeof(Color) incorrect!");
 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_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_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_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;
 		return 0;
 	case CommonFormat::XYf:
 	case CommonFormat::XYf:
 		return sizeof(float) * 2;
 		return sizeof(float) * 2;
+	case CommonFormat::XYZf:
+		return sizeof(float) * 3;
 	case CommonFormat::RGBAub:
 	case CommonFormat::RGBAub:
 		return sizeof(uint8) * 4;
 		return sizeof(uint8) * 4;
+	case CommonFormat::STf_RGBAub:
+		return sizeof(STf_RGBAub);
+	case CommonFormat::STPf_RGBAub:
+		return sizeof(STPf_RGBAub);
 	case CommonFormat::XYf_STf:
 	case CommonFormat::XYf_STf:
 		return sizeof(XYf_STf);
 		return sizeof(XYf_STf);
 	case CommonFormat::XYf_STPf:
 	case CommonFormat::XYf_STPf:
@@ -65,9 +73,13 @@ uint32 getFormatFlags(CommonFormat format)
 	case CommonFormat::NONE:
 	case CommonFormat::NONE:
 		return 0;
 		return 0;
 	case CommonFormat::XYf:
 	case CommonFormat::XYf:
+	case CommonFormat::XYZf:
 		return ATTRIBFLAG_POS;
 		return ATTRIBFLAG_POS;
 	case CommonFormat::RGBAub:
 	case CommonFormat::RGBAub:
 		return ATTRIBFLAG_COLOR;
 		return ATTRIBFLAG_COLOR;
+	case CommonFormat::STf_RGBAub:
+	case CommonFormat::STPf_RGBAub:
+		return ATTRIBFLAG_TEXCOORD | ATTRIB_COLOR;
 	case CommonFormat::XYf_STf:
 	case CommonFormat::XYf_STf:
 	case CommonFormat::XYf_STPf:
 	case CommonFormat::XYf_STPf:
 		return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
 		return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD;
@@ -75,7 +87,6 @@ uint32 getFormatFlags(CommonFormat format)
 	case CommonFormat::XYf_STus_RGBAub:
 	case CommonFormat::XYf_STus_RGBAub:
 	case CommonFormat::XYf_STPf_RGBAub:
 	case CommonFormat::XYf_STPf_RGBAub:
 		return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR;
 		return ATTRIBFLAG_POS | ATTRIBFLAG_TEXCOORD | ATTRIBFLAG_COLOR;
-
 	}
 	}
 }
 }
 
 
@@ -85,6 +96,8 @@ int getFormatPositionComponents(CommonFormat format)
 	{
 	{
 	case CommonFormat::NONE:
 	case CommonFormat::NONE:
 	case CommonFormat::RGBAub:
 	case CommonFormat::RGBAub:
+	case CommonFormat::STf_RGBAub:
+	case CommonFormat::STPf_RGBAub:
 		return 0;
 		return 0;
 	case CommonFormat::XYf:
 	case CommonFormat::XYf:
 	case CommonFormat::XYf_STf:
 	case CommonFormat::XYf_STf:
@@ -93,6 +106,8 @@ int getFormatPositionComponents(CommonFormat format)
 	case CommonFormat::XYf_STus_RGBAub:
 	case CommonFormat::XYf_STus_RGBAub:
 	case CommonFormat::XYf_STPf_RGBAub:
 	case CommonFormat::XYf_STPf_RGBAub:
 		return 2;
 		return 2;
+	case CommonFormat::XYZf:
+		return 3;
 	}
 	}
 }
 }
 
 

+ 20 - 0
src/modules/graphics/vertex.h

@@ -95,7 +95,10 @@ enum class CommonFormat
 {
 {
 	NONE,
 	NONE,
 	XYf,
 	XYf,
+	XYZf,
 	RGBAub,
 	RGBAub,
+	STf_RGBAub,
+	STPf_RGBAub,
 	XYf_STf,
 	XYf_STf,
 	XYf_STPf,
 	XYf_STPf,
 	XYf_STf_RGBAub,
 	XYf_STf_RGBAub,
@@ -103,6 +106,18 @@ enum class CommonFormat
 	XYf_STPf_RGBAub,
 	XYf_STPf_RGBAub,
 };
 };
 
 
+struct STf_RGBAub
+{
+	float s, t;
+	Color color;
+};
+
+struct STPf_RGBAub
+{
+	float s, t, p;
+	Color color;
+};
+
 struct XYf_STf
 struct XYf_STf
 {
 {
 	float x, y;
 	float x, y;
@@ -142,6 +157,11 @@ uint32 getFormatFlags(CommonFormat format);
 
 
 int getFormatPositionComponents(CommonFormat format);
 int getFormatPositionComponents(CommonFormat format);
 
 
+inline CommonFormat getSinglePositionFormat(bool is2D)
+{
+	return is2D ? CommonFormat::XYf : CommonFormat::XYZf;
+}
+
 size_t getIndexDataSize(IndexDataType type);
 size_t getIndexDataSize(IndexDataType type);
 
 
 IndexDataType getIndexDataTypeFromMax(size_t maxvalue);
 IndexDataType getIndexDataTypeFromMax(size_t maxvalue);