mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
Meshes expose vertex buffers, part 1
(compiles, but is currently half-implemented and broken)
This commit is contained in:
@@ -29,7 +29,9 @@ namespace graphics
|
||||
love::Type Buffer::type("GraphicsBuffer", &Object::type);
|
||||
|
||||
Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags)
|
||||
: size(size)
|
||||
: arrayLength(0)
|
||||
, arrayStride(0)
|
||||
, size(size)
|
||||
, typeFlags(typeflags)
|
||||
, usage(usage)
|
||||
, mapFlags(mapflags)
|
||||
@@ -37,12 +39,14 @@ Buffer::Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32
|
||||
{
|
||||
}
|
||||
|
||||
Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMember> &format, size_t arraylength)
|
||||
Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMember> &dataMembers, size_t arraylength)
|
||||
: Buffer(0, settings.typeFlags, settings.usage, settings.mapFlags)
|
||||
{
|
||||
if (format.size() == 0)
|
||||
if (dataMembers.size() == 0)
|
||||
throw love::Exception("Data format must contain values.");
|
||||
|
||||
this->dataMembers = dataMembers;
|
||||
|
||||
bool supportsGLSL3 = gfx->getCapabilities().features[Graphics::FEATURE_GLSL3];
|
||||
|
||||
bool uniformbuffer = settings.typeFlags & BUFFERFLAG_UNIFORM;
|
||||
@@ -50,13 +54,13 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMe
|
||||
bool vertexbuffer = settings.typeFlags & BUFFERFLAG_VERTEX;
|
||||
bool ssbuffer = settings.typeFlags & BUFFERFLAG_SHADER_STORAGE;
|
||||
|
||||
if (indexbuffer && format.size() > 1)
|
||||
if (indexbuffer && dataMembers.size() > 1)
|
||||
throw love::Exception("test");
|
||||
|
||||
size_t offset = 0;
|
||||
size_t stride = 0;
|
||||
|
||||
for (const auto &member : format)
|
||||
for (const auto &member : dataMembers)
|
||||
{
|
||||
DataFormat format = member.format;
|
||||
const DataFormatInfo &info = getDataFormatInfo(format);
|
||||
@@ -85,11 +89,26 @@ Buffer::Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMe
|
||||
throw love::Exception("");
|
||||
}
|
||||
}
|
||||
|
||||
this->arrayLength = arraylength;
|
||||
this->arrayStride = stride;
|
||||
this->size = stride * arraylength;
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
}
|
||||
|
||||
int Buffer::getDataMemberIndex(const std::string &name) const
|
||||
{
|
||||
for (size_t i = 0; i < dataMembers.size(); i++)
|
||||
{
|
||||
if (dataMembers[i].name == name)
|
||||
return (int) i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // graphics
|
||||
} // love
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
};
|
||||
|
||||
Buffer(size_t size, BufferTypeFlags typeflags, BufferUsage usage, uint32 mapflags);
|
||||
Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMember> &format, size_t arraylength);
|
||||
Buffer(Graphics *gfx, const Settings &settings, const std::vector<DataMember> &members, size_t arraylength);
|
||||
virtual ~Buffer();
|
||||
|
||||
size_t getSize() const { return size; }
|
||||
@@ -78,6 +78,13 @@ public:
|
||||
bool isMapped() const { return mapped; }
|
||||
uint32 getMapFlags() const { return mapFlags; }
|
||||
|
||||
size_t getArrayLength() const { return arrayLength; }
|
||||
size_t getArrayStride() const { return arrayStride; }
|
||||
const std::vector<DataMember> &getDataMembers() const { return dataMembers; }
|
||||
const DataMember &getDataMember(int index) const { return dataMembers[index]; }
|
||||
size_t getMemberOffset(int index) const { return memberOffsets[index]; }
|
||||
int getDataMemberIndex(const std::string &name) const;
|
||||
|
||||
/**
|
||||
* Map the Buffer to client memory.
|
||||
*
|
||||
@@ -138,8 +145,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<DataMember> format;
|
||||
std::vector<DataMember> dataMembers;
|
||||
std::vector<size_t> memberOffsets;
|
||||
size_t arrayLength;
|
||||
size_t arrayStride;
|
||||
|
||||
// The size of the buffer, in bytes.
|
||||
|
||||
@@ -125,8 +125,8 @@ Mesh::~Mesh()
|
||||
|
||||
for (const auto &attrib : attachedAttributes)
|
||||
{
|
||||
if (attrib.second.mesh != this)
|
||||
attrib.second.mesh->release();
|
||||
if (attrib.second.buffer != nullptr && attrib.second.buffer != vertexBuffer.get())
|
||||
attrib.second.buffer->release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ void Mesh::setupAttachedAttributes()
|
||||
if (attachedAttributes.find(name) != attachedAttributes.end())
|
||||
throw love::Exception("Duplicate vertex attribute name: %s", name.c_str());
|
||||
|
||||
attachedAttributes[name] = {this, (int) i, STEP_PER_VERTEX, true};
|
||||
attachedAttributes[name] = {nullptr, (int) i, STEP_PER_VERTEX, true};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,11 @@ size_t Mesh::getVertexStride() const
|
||||
return vertexStride;
|
||||
}
|
||||
|
||||
Buffer *Mesh::getVertexBuffer() const
|
||||
{
|
||||
return vertexBuffer;
|
||||
}
|
||||
|
||||
const std::vector<Mesh::AttribFormat> &Mesh::getVertexFormat() const
|
||||
{
|
||||
return vertexFormat;
|
||||
@@ -305,23 +310,15 @@ bool Mesh::isAttributeEnabled(const std::string &name) const
|
||||
return it->second.enabled;
|
||||
}
|
||||
|
||||
void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step)
|
||||
void Mesh::attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step)
|
||||
{
|
||||
if ((buffer->getTypeFlags() & BUFFER_VERTEX) == 0)
|
||||
throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a Mesh vertex attribute.");
|
||||
|
||||
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
|
||||
if (step == STEP_PER_INSTANCE && !gfx->getCapabilities().features[Graphics::FEATURE_INSTANCING])
|
||||
throw love::Exception("Vertex attribute instancing is not supported on this system.");
|
||||
|
||||
if (mesh != this)
|
||||
{
|
||||
for (const auto &it : mesh->attachedAttributes)
|
||||
{
|
||||
// If the supplied Mesh has attached attributes of its own, then we
|
||||
// prevent it from being attached to avoid reference cycles.
|
||||
if (it.second.mesh != mesh)
|
||||
throw love::Exception("Cannot attach a Mesh which has attached Meshes of its own.");
|
||||
}
|
||||
}
|
||||
|
||||
AttachedAttribute oldattrib = {};
|
||||
AttachedAttribute newattrib = {};
|
||||
|
||||
@@ -331,34 +328,33 @@ void Mesh::attachAttribute(const std::string &name, Mesh *mesh, const std::strin
|
||||
else if (attachedAttributes.size() + 1 > VertexAttributes::MAX)
|
||||
throw love::Exception("A maximum of %d attributes can be attached at once.", VertexAttributes::MAX);
|
||||
|
||||
newattrib.mesh = mesh;
|
||||
newattrib.enabled = oldattrib.mesh ? oldattrib.enabled : true;
|
||||
newattrib.index = mesh->getAttributeIndex(attachname);
|
||||
newattrib.buffer = buffer;
|
||||
newattrib.enabled = oldattrib.buffer ? oldattrib.enabled : true;
|
||||
newattrib.index = buffer->getDataMemberIndex(attachname);
|
||||
newattrib.step = step;
|
||||
|
||||
if (newattrib.index < 0)
|
||||
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", attachname.c_str());
|
||||
throw love::Exception("The specified vertex buffer does not have a vertex attribute named '%s'", attachname.c_str());
|
||||
|
||||
if (newattrib.mesh != this)
|
||||
newattrib.mesh->retain();
|
||||
newattrib.buffer->retain();
|
||||
|
||||
attachedAttributes[name] = newattrib;
|
||||
|
||||
if (oldattrib.mesh && oldattrib.mesh != this)
|
||||
oldattrib.mesh->release();
|
||||
if (oldattrib.buffer)
|
||||
oldattrib.buffer->release();
|
||||
}
|
||||
|
||||
bool Mesh::detachAttribute(const std::string &name)
|
||||
{
|
||||
auto it = attachedAttributes.find(name);
|
||||
|
||||
if (it != attachedAttributes.end() && it->second.mesh != this)
|
||||
if (it != attachedAttributes.end() && it->second.buffer != vertexBuffer.get())
|
||||
{
|
||||
it->second.mesh->release();
|
||||
it->second.buffer->release();
|
||||
attachedAttributes.erase(it);
|
||||
|
||||
if (getAttributeIndex(name) != -1)
|
||||
attachAttribute(name, this, name);
|
||||
attachAttribute(name, vertexBuffer, name);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -590,7 +586,7 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
|
||||
if (!attrib.second.enabled)
|
||||
continue;
|
||||
|
||||
Mesh *mesh = attrib.second.mesh;
|
||||
Buffer *buffer = attrib.second.buffer;
|
||||
int attributeindex = -1;
|
||||
|
||||
// If the attribute is one of the LOVE-defined ones, use the constant
|
||||
@@ -604,19 +600,18 @@ void Mesh::drawInstanced(Graphics *gfx, const Matrix4 &m, int instancecount)
|
||||
if (attributeindex >= 0)
|
||||
{
|
||||
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
|
||||
mesh->vertexBuffer->unmap();
|
||||
buffer->unmap();
|
||||
|
||||
const auto &formats = mesh->getVertexFormat();
|
||||
const auto &format = formats[attrib.second.index];
|
||||
const auto &member = buffer->getDataMember(attrib.second.index);
|
||||
|
||||
uint16 offset = (uint16) mesh->getAttributeOffset(attrib.second.index);
|
||||
uint16 stride = (uint16) mesh->getVertexStride();
|
||||
uint16 offset = (uint16) buffer->getMemberOffset(attrib.second.index);
|
||||
uint16 stride = (uint16) buffer->getArrayStride();
|
||||
|
||||
attributes.set(attributeindex, format.type, (uint8) format.components, offset, activebuffers);
|
||||
attributes.set(attributeindex, member.format, offset, activebuffers);
|
||||
attributes.setBufferLayout(activebuffers, stride, attrib.second.step);
|
||||
|
||||
// TODO: Ideally we want to reuse buffers with the same stride+step.
|
||||
buffers.set(activebuffers, mesh->vertexBuffer, 0);
|
||||
buffers.set(activebuffers, buffer, 0);
|
||||
activebuffers++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,8 @@ public:
|
||||
**/
|
||||
size_t getVertexStride() const;
|
||||
|
||||
Buffer *getVertexBuffer() const;
|
||||
|
||||
/**
|
||||
* Gets the format of each vertex attribute stored in the Mesh.
|
||||
**/
|
||||
@@ -106,10 +108,10 @@ public:
|
||||
bool isAttributeEnabled(const std::string &name) const;
|
||||
|
||||
/**
|
||||
* Attaches a vertex attribute from another Mesh to this one. The attribute
|
||||
* will be used when drawing this Mesh.
|
||||
* Attaches a vertex attribute from another vertex buffer to this Mesh. The
|
||||
* attribute will be used when drawing this Mesh.
|
||||
**/
|
||||
void attachAttribute(const std::string &name, Mesh *mesh, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX);
|
||||
void attachAttribute(const std::string &name, Buffer *buffer, const std::string &attachname, AttributeStep step = STEP_PER_VERTEX);
|
||||
bool detachAttribute(const std::string &name);
|
||||
|
||||
void *mapVertexData();
|
||||
@@ -180,7 +182,7 @@ private:
|
||||
|
||||
struct AttachedAttribute
|
||||
{
|
||||
Mesh *mesh;
|
||||
Buffer *buffer;
|
||||
int index;
|
||||
AttributeStep step;
|
||||
bool enabled;
|
||||
|
||||
@@ -244,24 +244,27 @@ int SpriteBatch::getBufferSize() const
|
||||
return size;
|
||||
}
|
||||
|
||||
void SpriteBatch::attachAttribute(const std::string &name, Mesh *mesh)
|
||||
void SpriteBatch::attachAttribute(const std::string &name, Buffer *buffer)
|
||||
{
|
||||
if ((buffer->getTypeFlags() & BUFFER_VERTEX) == 0)
|
||||
throw love::Exception("GraphicsBuffer must be created with vertex buffer support to be used as a SpriteBatch vertex attribute.");
|
||||
|
||||
AttachedAttribute oldattrib = {};
|
||||
AttachedAttribute newattrib = {};
|
||||
|
||||
if (mesh->getVertexCount() < (size_t) next * 4)
|
||||
throw love::Exception("Mesh has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4);
|
||||
if (buffer->getArrayLength() < (size_t) next * 4)
|
||||
throw love::Exception("Buffer has too few vertices to be attached to this SpriteBatch (at least %d vertices are required)", next*4);
|
||||
|
||||
auto it = attached_attributes.find(name);
|
||||
if (it != attached_attributes.end())
|
||||
oldattrib = it->second;
|
||||
|
||||
newattrib.index = mesh->getAttributeIndex(name);
|
||||
newattrib.index = buffer->getDataMemberIndex(name);
|
||||
|
||||
if (newattrib.index < 0)
|
||||
throw love::Exception("The specified mesh does not have a vertex attribute named '%s'", name.c_str());
|
||||
throw love::Exception("The specified Buffer does not have a vertex attribute named '%s'", name.c_str());
|
||||
|
||||
newattrib.mesh = mesh;
|
||||
newattrib.buffer = buffer;
|
||||
|
||||
attached_attributes[name] = newattrib;
|
||||
}
|
||||
@@ -327,12 +330,12 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
||||
|
||||
for (const auto &it : attached_attributes)
|
||||
{
|
||||
Mesh *mesh = it.second.mesh.get();
|
||||
Buffer *buffer = it.second.buffer.get();
|
||||
|
||||
// We have to do this check here as wll because setBufferSize can be
|
||||
// called after attachAttribute.
|
||||
if (mesh->getVertexCount() < (size_t) next * 4)
|
||||
throw love::Exception("Mesh with attribute '%s' attached to this SpriteBatch has too few vertices", it.first.c_str());
|
||||
if (buffer->getArrayLength() < (size_t) next * 4)
|
||||
throw love::Exception("Buffer with attribute '%s' attached to this SpriteBatch has too few vertices", it.first.c_str());
|
||||
|
||||
int attributeindex = -1;
|
||||
|
||||
@@ -347,19 +350,18 @@ void SpriteBatch::draw(Graphics *gfx, const Matrix4 &m)
|
||||
if (attributeindex >= 0)
|
||||
{
|
||||
// Make sure the buffer isn't mapped (sends data to GPU if needed.)
|
||||
mesh->vertexBuffer->unmap();
|
||||
buffer->unmap();
|
||||
|
||||
const auto &formats = mesh->getVertexFormat();
|
||||
const auto &format = formats[it.second.index];
|
||||
const auto &member = buffer->getDataMember(it.second.index);
|
||||
|
||||
uint16 offset = (uint16) mesh->getAttributeOffset(it.second.index);
|
||||
uint16 stride = (uint16) mesh->getVertexStride();
|
||||
uint16 offset = (uint16) buffer->getMemberOffset(it.second.index);
|
||||
uint16 stride = (uint16) buffer->getArrayStride();
|
||||
|
||||
attributes.set(attributeindex, format.type, (uint8) format.components, offset, activebuffers);
|
||||
attributes.set(attributeindex, member.format, offset, activebuffers);
|
||||
attributes.setBufferLayout(activebuffers, stride);
|
||||
|
||||
// TODO: We should reuse buffer bindings with the same buffer+stride+step.
|
||||
buffers.set(activebuffers, mesh->vertexBuffer, 0);
|
||||
buffers.set(activebuffers, buffer, 0);
|
||||
activebuffers++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
* Attaches a specific vertex attribute from a Mesh to this SpriteBatch.
|
||||
* The vertex attribute will be used when drawing the SpriteBatch.
|
||||
**/
|
||||
void attachAttribute(const std::string &name, Mesh *mesh);
|
||||
void attachAttribute(const std::string &name, Buffer *buffer);
|
||||
|
||||
void setDrawRange(int start, int count);
|
||||
void setDrawRange();
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
|
||||
struct AttachedAttribute
|
||||
{
|
||||
StrongRef<Mesh> mesh;
|
||||
StrongRef<Buffer> buffer;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
@@ -631,47 +631,151 @@ GLenum OpenGL::getGLIndexDataType(IndexDataType type)
|
||||
}
|
||||
}
|
||||
|
||||
GLenum OpenGL::getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat)
|
||||
GLenum OpenGL::getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat)
|
||||
{
|
||||
normalized = GL_FALSE;
|
||||
intformat = false;
|
||||
components = 1;
|
||||
|
||||
switch (type)
|
||||
switch (format)
|
||||
{
|
||||
case DATA_SNORM8:
|
||||
normalized = GL_TRUE;
|
||||
return GL_BYTE;
|
||||
case DATA_UNORM8:
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case DATA_INT8:
|
||||
intformat = true;
|
||||
return GL_BYTE;
|
||||
case DATA_UINT8:
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case DATA_SNORM16:
|
||||
normalized = GL_TRUE;
|
||||
return GL_SHORT;
|
||||
case DATA_UNORM16:
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATA_INT16:
|
||||
intformat = true;
|
||||
return GL_SHORT;
|
||||
case DATA_UINT16:
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATA_INT32:
|
||||
case DATAFORMAT_FLOAT:
|
||||
components = 1;
|
||||
return GL_FLOAT;
|
||||
case DATAFORMAT_FLOAT_VEC2:
|
||||
components = 2;
|
||||
return GL_FLOAT;
|
||||
case DATAFORMAT_FLOAT_VEC3:
|
||||
components = 3;
|
||||
return GL_FLOAT;
|
||||
case DATAFORMAT_FLOAT_VEC4:
|
||||
components = 4;
|
||||
return GL_FLOAT;
|
||||
|
||||
case DATAFORMAT_FLOAT_MAT2X2:
|
||||
case DATAFORMAT_FLOAT_MAT2X3:
|
||||
case DATAFORMAT_FLOAT_MAT2X4:
|
||||
case DATAFORMAT_FLOAT_MAT3X2:
|
||||
case DATAFORMAT_FLOAT_MAT3X3:
|
||||
case DATAFORMAT_FLOAT_MAT3X4:
|
||||
case DATAFORMAT_FLOAT_MAT4X2:
|
||||
case DATAFORMAT_FLOAT_MAT4X3:
|
||||
case DATAFORMAT_FLOAT_MAT4X4:
|
||||
return GL_ZERO;
|
||||
|
||||
case DATAFORMAT_INT32:
|
||||
components = 1;
|
||||
intformat = true;
|
||||
return GL_INT;
|
||||
case DATA_UINT32:
|
||||
case DATAFORMAT_INT32_VEC2:
|
||||
components = 2;
|
||||
intformat = true;
|
||||
return GL_INT;
|
||||
case DATAFORMAT_INT32_VEC3:
|
||||
components = 3;
|
||||
intformat = true;
|
||||
return GL_INT;
|
||||
case DATAFORMAT_INT32_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_INT;
|
||||
|
||||
case DATAFORMAT_UINT32:
|
||||
components = 1;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_INT;
|
||||
case DATA_FLOAT:
|
||||
normalized = GL_FALSE;
|
||||
return GL_FLOAT;
|
||||
case DATA_MAX_ENUM:
|
||||
case DATAFORMAT_UINT32_VEC2:
|
||||
components = 2;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_INT;
|
||||
case DATAFORMAT_UINT32_VEC3:
|
||||
components = 3;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_INT;
|
||||
case DATAFORMAT_UINT32_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_INT;
|
||||
|
||||
case DATAFORMAT_SNORM8_VEC4:
|
||||
components = 4;
|
||||
normalized = GL_TRUE;
|
||||
return GL_BYTE;
|
||||
|
||||
case DATAFORMAT_UNORM8_VEC4:
|
||||
components = 4;
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_BYTE;
|
||||
|
||||
case DATAFORMAT_INT8_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_BYTE;
|
||||
|
||||
case DATAFORMAT_UINT8_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_BYTE;
|
||||
|
||||
case DATAFORMAT_SNORM16:
|
||||
components = 1;
|
||||
normalized = GL_TRUE;
|
||||
return GL_SHORT;
|
||||
case DATAFORMAT_SNORM16_VEC2:
|
||||
components = 2;
|
||||
normalized = GL_TRUE;
|
||||
return GL_BYTE;
|
||||
case DATAFORMAT_SNORM16_VEC4:
|
||||
components = 4;
|
||||
normalized = GL_TRUE;
|
||||
return GL_BYTE;
|
||||
|
||||
case DATAFORMAT_UNORM16:
|
||||
components = 1;
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATAFORMAT_UNORM16_VEC2:
|
||||
components = 2;
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATAFORMAT_UNORM16_VEC4:
|
||||
components = 4;
|
||||
normalized = GL_TRUE;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
|
||||
case DATAFORMAT_INT16:
|
||||
components = 1;
|
||||
intformat = true;
|
||||
return GL_SHORT;
|
||||
case DATAFORMAT_INT16_VEC2:
|
||||
components = 2;
|
||||
intformat = true;
|
||||
return GL_SHORT;
|
||||
case DATAFORMAT_INT16_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_SHORT;
|
||||
|
||||
case DATAFORMAT_UINT16:
|
||||
components = 1;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATAFORMAT_UINT16_VEC2:
|
||||
components = 2;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case DATAFORMAT_UINT16_VEC4:
|
||||
components = 4;
|
||||
intformat = true;
|
||||
return GL_UNSIGNED_SHORT;
|
||||
|
||||
case DATAFORMAT_BOOL:
|
||||
case DATAFORMAT_BOOL_VEC2:
|
||||
case DATAFORMAT_BOOL_VEC3:
|
||||
case DATAFORMAT_BOOL_VEC4:
|
||||
return GL_ZERO;
|
||||
|
||||
case DATAFORMAT_MAX_ENUM:
|
||||
return GL_ZERO;
|
||||
}
|
||||
|
||||
@@ -746,18 +850,19 @@ void OpenGL::setVertexAttributes(const VertexAttributes &attributes, const Buffe
|
||||
if ((state.instancedAttribArrays & bit) ^ divisorbit)
|
||||
glVertexAttribDivisor(i, divisor);
|
||||
|
||||
int components = 0;
|
||||
GLboolean normalized = GL_FALSE;
|
||||
bool intformat = false;
|
||||
GLenum gltype = getGLVertexDataType(attrib.type, normalized, intformat);
|
||||
GLenum gltype = getGLVertexDataType(attrib.format, components, normalized, intformat);
|
||||
|
||||
const void *offsetpointer = reinterpret_cast<void*>(bufferinfo.offset + attrib.offsetFromVertex);
|
||||
|
||||
bindBuffer(BUFFER_VERTEX, (GLuint) bufferinfo.buffer->getHandle());
|
||||
|
||||
if (intformat)
|
||||
glVertexAttribIPointer(i, attrib.components, gltype, layout.stride, offsetpointer);
|
||||
glVertexAttribIPointer(i, components, gltype, layout.stride, offsetpointer);
|
||||
else
|
||||
glVertexAttribPointer(i, attrib.components, gltype, normalized, layout.stride, offsetpointer);
|
||||
glVertexAttribPointer(i, components, gltype, normalized, layout.stride, offsetpointer);
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
@@ -404,7 +404,7 @@ public:
|
||||
static GLenum getGLPrimitiveType(PrimitiveType type);
|
||||
static GLenum getGLBufferType(BufferType type);
|
||||
static GLenum getGLIndexDataType(IndexDataType type);
|
||||
static GLenum getGLVertexDataType(DataType type, GLboolean &normalized, bool &intformat);
|
||||
static GLenum getGLVertexDataType(DataFormat format, int &components, GLboolean &normalized, bool &intformat);
|
||||
static GLenum getGLBufferUsage(BufferUsage usage);
|
||||
static GLenum getGLTextureType(TextureType type);
|
||||
static GLint getGLWrapMode(Texture::WrapMode wmode);
|
||||
|
||||
@@ -309,44 +309,44 @@ void VertexAttributes::setCommonFormat(CommonFormat format, uint8 bufferindex)
|
||||
case CommonFormat::NONE:
|
||||
break;
|
||||
case CommonFormat::XYf:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYZf:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 3, 0, bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC3, 0, bufferindex);
|
||||
break;
|
||||
case CommonFormat::RGBAub:
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, 0, bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, 0, bufferindex);
|
||||
break;
|
||||
case CommonFormat::STf_RGBAub:
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 2), bufferindex);
|
||||
break;
|
||||
case CommonFormat::STPf_RGBAub:
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, 0, bufferindex);
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 3), bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, 0, bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 3), bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYf_STf:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, uint16(sizeof(float) * 2), bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYf_STPf:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, uint16(sizeof(float) * 2), bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYf_STf_RGBAub:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 2, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 4), bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC2, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 4), bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYf_STus_RGBAub:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATA_UNORM16, 2, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 2 + sizeof(uint16) * 2), bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_UNORM16_VEC2, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 2 + sizeof(uint16) * 2), bufferindex);
|
||||
break;
|
||||
case CommonFormat::XYf_STPf_RGBAub:
|
||||
set(ATTRIB_POS, DATA_FLOAT, 2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATA_FLOAT, 3, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATA_UNORM8, 4, uint16(sizeof(float) * 5), bufferindex);
|
||||
set(ATTRIB_POS, DATAFORMAT_FLOAT_VEC2, 0, bufferindex);
|
||||
set(ATTRIB_TEXCOORD, DATAFORMAT_FLOAT_VEC3, uint16(sizeof(float) * 2), bufferindex);
|
||||
set(ATTRIB_COLOR, DATAFORMAT_UNORM8_VEC4, uint16(sizeof(float) * 5), bufferindex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,8 +320,7 @@ struct BufferBindings
|
||||
struct VertexAttributeInfo
|
||||
{
|
||||
uint8 bufferIndex;
|
||||
DataType type : 4;
|
||||
uint8 components : 4;
|
||||
DataFormat format : 8;
|
||||
uint16 offsetFromVertex;
|
||||
};
|
||||
|
||||
@@ -346,13 +345,12 @@ struct VertexAttributes
|
||||
setCommonFormat(format, bufferindex);
|
||||
}
|
||||
|
||||
void set(uint32 index, DataType type, uint8 components, uint16 offsetfromvertex, uint8 bufferindex)
|
||||
void set(uint32 index, DataFormat format, uint16 offsetfromvertex, uint8 bufferindex)
|
||||
{
|
||||
enableBits |= (1u << index);
|
||||
|
||||
attribs[index].bufferIndex = bufferindex;
|
||||
attribs[index].type = type;
|
||||
attribs[index].components = components;
|
||||
attribs[index].format = format;
|
||||
attribs[index].offsetFromVertex = offsetfromvertex;
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,17 @@ int w_Mesh_attachAttribute(lua_State *L)
|
||||
{
|
||||
Mesh *t = luax_checkmesh(L, 1);
|
||||
const char *name = luaL_checkstring(L, 2);
|
||||
Mesh *mesh = luax_checkmesh(L, 3);
|
||||
|
||||
Buffer *buffer = nullptr;
|
||||
if (luax_istype(L, 3, Buffer::type))
|
||||
{
|
||||
buffer = luax_checktype<Buffer>(L, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mesh *mesh = luax_checkmesh(L, 3);
|
||||
buffer = mesh->getVertexBuffer();
|
||||
}
|
||||
|
||||
AttributeStep step = STEP_PER_VERTEX;
|
||||
const char *stepstr = lua_isnoneornil(L, 4) ? nullptr : luaL_checkstring(L, 4);
|
||||
@@ -425,7 +435,7 @@ int w_Mesh_attachAttribute(lua_State *L)
|
||||
|
||||
const char *attachname = luaL_optstring(L, 5, name);
|
||||
|
||||
luax_catchexcept(L, [&](){ t->attachAttribute(name, mesh, attachname, step); });
|
||||
luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer, attachname, step); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -226,9 +226,19 @@ int w_SpriteBatch_attachAttribute(lua_State *L)
|
||||
{
|
||||
SpriteBatch *t = luax_checkspritebatch(L, 1);
|
||||
const char *name = luaL_checkstring(L, 2);
|
||||
Mesh *m = luax_checktype<Mesh>(L, 3);
|
||||
|
||||
luax_catchexcept(L, [&](){ t->attachAttribute(name, m); });
|
||||
Buffer *buffer = nullptr;
|
||||
if (luax_istype(L, 3, Buffer::type))
|
||||
{
|
||||
buffer = luax_checktype<Buffer>(L, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Mesh *mesh = luax_checktype<Mesh>(L, 3);
|
||||
buffer = mesh->getVertexBuffer();
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&](){ t->attachAttribute(name, buffer); });
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user