diff --git a/doomsday/libgui/include/de/gui/gluniform.h b/doomsday/libgui/include/de/gui/gluniform.h index d126ec3a4c..cd33b236a8 100644 --- a/doomsday/libgui/include/de/gui/gluniform.h +++ b/doomsday/libgui/include/de/gui/gluniform.h @@ -61,7 +61,8 @@ class LIBGUI_PUBLIC GLUniform Vec4, Mat3, Mat4, - Sampler2D + Sampler2D, + Mat4Array }; /** @@ -75,7 +76,7 @@ class LIBGUI_PUBLIC GLUniform DENG2_DEFINE_AUDIENCE2(Deletion, void uniformDeleted(GLUniform &)) public: - GLUniform(char const *nameInShader, Type uniformType); + GLUniform(char const *nameInShader, Type uniformType, duint elements = 1); void setName(char const *nameInShader); @@ -97,10 +98,12 @@ class LIBGUI_PUBLIC GLUniform GLUniform &operator = (Vector3f const &vec); GLUniform &operator = (Vector4f const &vec); GLUniform &operator = (Matrix3f const &vec); - GLUniform &operator = (Matrix4f const &vec); + GLUniform &operator = (Matrix4f const &mat); GLUniform &operator = (GLTexture const &texture); GLUniform &operator = (GLTexture const *texture); + GLUniform &set(duint elementIndex, Matrix4f const &mat); + operator dint() const { return toInt(); } operator duint() const { return toUInt(); } operator dfloat() const { return toFloat(); } diff --git a/doomsday/libgui/src/gluniform.cpp b/doomsday/libgui/src/gluniform.cpp index a0b90e437a..a29f7c1da7 100644 --- a/doomsday/libgui/src/gluniform.cpp +++ b/doomsday/libgui/src/gluniform.cpp @@ -38,14 +38,21 @@ DENG2_PIMPL(GLUniform) Vector4f *vector; Matrix3f *mat3; Matrix4f *mat4; - GLTexture const *tex; + GLTexture const *tex; } value; + duint elemCount; - Instance(Public *i, QLatin1String const &n, Type t) - : Base(i), name(n.latin1()), type(t) + Instance(Public *i, QLatin1String const &n, Type t, duint elems) + : Base(i) + , name(n.latin1()) + , type(t) + , elemCount(elems) { name.append('\0'); + DENG2_ASSERT((type == Mat4Array && elemCount >= 1) || + (type != Mat4Array && elemCount == 1)); + // Allocate the value type. zap(value); switch(type) @@ -64,6 +71,10 @@ DENG2_PIMPL(GLUniform) value.mat4 = new Matrix4f; break; + case Mat4Array: + value.mat4 = new Matrix4f[elemCount]; + break; + default: break; } @@ -89,6 +100,10 @@ DENG2_PIMPL(GLUniform) delete value.mat4; break; + case Mat4Array: + delete [] value.mat4; + break; + case Sampler2D: if(value.tex) value.tex->audienceForDeletion() -= this; break; @@ -166,8 +181,8 @@ DENG2_PIMPL(GLUniform) DENG2_AUDIENCE_METHOD(GLUniform, Deletion) DENG2_AUDIENCE_METHOD(GLUniform, ValueChange) -GLUniform::GLUniform(char const *nameInShader, Type uniformType) - : d(new Instance(this, QLatin1String(nameInShader), uniformType)) +GLUniform::GLUniform(char const *nameInShader, Type uniformType, duint elements) + : d(new Instance(this, QLatin1String(nameInShader), uniformType, elements)) {} void GLUniform::setName(char const *nameInShader) @@ -296,6 +311,17 @@ GLUniform &GLUniform::operator = (GLTexture const *texture) return *this; } +GLUniform &GLUniform::set(duint elementIndex, Matrix4f const &mat) +{ + DENG2_ASSERT(d->type == Mat4Array); + DENG2_ASSERT(elementIndex < d->elemCount); + + d->value.mat4[elementIndex] = mat; + d->markAsChanged(); + + return *this; +} + dint GLUniform::toInt() const { DENG2_ASSERT(d->type == Int || d->type == UInt || d->type == Float); @@ -407,34 +433,43 @@ void GLUniform::applyInProgram(GLProgram &program) const { case Int: glUniform1i(loc, d->value.int32); + LIBGUI_ASSERT_GL_OK(); break; case UInt: glUniform1i(loc, d->value.uint32); + LIBGUI_ASSERT_GL_OK(); break; case Float: glUniform1f(loc, d->value.float32); + LIBGUI_ASSERT_GL_OK(); break; case Vec2: glUniform2f(loc, d->value.vector->x, d->value.vector->y); + LIBGUI_ASSERT_GL_OK(); break; case Vec3: glUniform3f(loc, d->value.vector->x, d->value.vector->y, d->value.vector->z); + LIBGUI_ASSERT_GL_OK(); break; case Vec4: glUniform4f(loc, d->value.vector->x, d->value.vector->y, d->value.vector->z, d->value.vector->w); + LIBGUI_ASSERT_GL_OK(); break; case Mat3: glUniformMatrix3fv(loc, 1, GL_FALSE, d->value.mat3->values()); + LIBGUI_ASSERT_GL_OK(); break; case Mat4: - glUniformMatrix4fv(loc, 1, GL_FALSE, d->value.mat4->values()); + case Mat4Array: + glUniformMatrix4fv(loc, d->elemCount, GL_FALSE, d->value.mat4->values()); // sequentially laid out + LIBGUI_ASSERT_GL_OK(); break; default: