Permalink
Browse files

Uniform mapping

  • Loading branch information...
1 parent 8c8592b commit 283066fd7b7d904dc85ee5211357706d2ae2485e @tonttu committed Apr 20, 2012
Showing with 337 additions and 2 deletions.
  1. +53 −1 app/core/material.cpp
  2. +54 −1 app/core/material.hpp
  3. +2 −0 app/core/model.cpp
  4. +34 −0 app/gl/program.hpp
  5. +190 −0 app/gl/state.cpp
  6. +3 −0 app/gl/state.hpp
  7. +1 −0 app/main.cpp
View
@@ -24,6 +24,30 @@
#include "gl/camera.hpp"
#include "gui/properties.hpp"
+MappableValue::MappableValue(const QString& src, const QString& var, int index, const QString& selection)
+ : m_src(src), m_var(var), m_index(index), m_select(selection.size()) {
+ const QString tst = "xrsygtzbpwaq";
+ for (int i = 0; i < selection.size(); ++i) {
+ m_select[i] = tst.indexOf(selection[i].toAscii()) / 3;
+ }
+}
+
+MappableValue MappableValue::parse(const QString& input) {
+ QRegExp re("([a-z]+)" // src ("scene")
+ "(?:\\[(\\d+)\\])?" // optional: [4]
+ "\\." // .
+ "([a-z]+)" // variable ("width")
+ "(?:\\.([xyzwrgbastpq]{1,4}))?"); // optional .abgr
+ if (re.exactMatch(input)) {
+ return MappableValue(re.cap(1), re.cap(3),
+ re.cap(2).isEmpty() ? -1 : re.cap(2).toInt(),
+ re.cap(4));
+ } else {
+ Log::error("Failed to parse %s", input.toUtf8().data());
+ }
+ return MappableValue();
+}
+
Material::Material(QString name) : SceneObject(name), m_prog_binded(false) {
}
@@ -45,6 +69,20 @@ void Material::removeTexture(TexturePtr tex) {
emit changed(shared_from_this());
}
+void Material::setAttributeMapping(const QString& name, const QString& attr) {
+ MappableValue var = MappableValue::parse(attr);
+ if (!var.src().isEmpty()) {
+ m_attributeMap[name] = var;
+ }
+}
+
+void Material::setUniformMapping(const QString& name, const QString& attr) {
+ MappableValue var = MappableValue::parse(attr);
+ if (!var.src().isEmpty()) {
+ m_uniformMap[name] = var;
+ }
+}
+
Material::Colors::Colors()
: diffuse(0.8f, 0.8f, 0.8f, 1.0f),
specular(1.0f, 1.0f, 1.0f, 1.0f),
@@ -180,7 +218,21 @@ void Material::load(Scene& scene, QVariantMap map) {
/// @todo add a default shader if the material has shader hint
/// and prog is null
- QVariantMap tmp = map["textures"].toMap();
+ QVariantMap tmp = map["attributes"].toMap();
+ for (auto it = tmp.begin(); it != tmp.end(); ++it) {
+ QVariantMap attrMap = it.value().toMap();
+ if (attrMap.contains("map"))
+ setAttributeMapping(it.key(), attrMap["map"].toString());
+ }
+
+ tmp = map["uniforms"].toMap();
+ for (auto it = tmp.begin(); it != tmp.end(); ++it) {
+ QVariantMap uniformMap = it.value().toMap();
+ if (uniformMap.contains("map"))
+ setUniformMapping(it.key(), uniformMap["map"].toString());
+ }
+
+ tmp = map["textures"].toMap();
for (auto it = tmp.begin(); it != tmp.end(); ++it)
addTexture(it.key(), scene.genTexture(it.value().toString()));
}
View
@@ -26,9 +26,53 @@
#include "gl/uniform.hpp"
#include "gl/scene_object.hpp"
-#include <QVector3D>
#include <QString>
+/**
+ * This is used to make a mapping between uniform variables / attributes
+ * and Shaderkit variables. This class doesn't hold the uniform / attribute name,
+ * only the part that exactly defines one Shaderkit variable.
+ *
+ * For example the configuration file could have:
+ * "uniforms" : {
+ * "color" : {
+ * "map" : "material.diffuse"
+ * }
+ * }
+ * that would mean that the uniform variable named color is automatically
+ * set to active Material::Colors::diffuse.
+ */
+class MappableValue {
+public:
+ MappableValue(const QString& src, const QString& var, int index, const QString& selection);
+ MappableValue() : m_index(-1) {}
+
+ /// Variable category, for example "camera" or "material"
+ /// This is the name before .
+ const QString& src() const { return m_src; }
+
+ /// Variable name, for example "diffuse"
+ /// This is the name after .
+ const QString& var() const { return m_var; }
+
+ /// When using syntax "light[2].location", this is the index of the category
+ /// (2 in the example). Normally this is just -1
+ int index() const { return m_index; }
+
+ /// It's possible to use GLSL-like one to four component selection syntax
+ /// For example "material.emissive.rr" (vec2) or "material.ambient.argb" (vec4)
+ /// The supported names are xyzw / rgba / stpq
+ /// @return The list of indices or empty vector if no selection syntax was used
+ const std::vector<int>& select() const { return m_select; }
+
+ static MappableValue parse(const QString& input);
+
+private:
+ QString m_src, m_var;
+ int m_index;
+ std::vector<int> m_select;
+};
+
class Material : public QObject, public std::enable_shared_from_this<Material>,
public SceneObject {
Q_OBJECT
@@ -40,6 +84,9 @@ class Material : public QObject, public std::enable_shared_from_this<Material>,
void setTexture(QString name, TexturePtr tex);
void removeTexture(TexturePtr tex);
+ void setAttributeMapping(const QString& name, const QString& attr);
+ void setUniformMapping(const QString& name, const QString& attr);
+
struct Colors {
Colors();
Color diffuse;
@@ -82,6 +129,9 @@ class Material : public QObject, public std::enable_shared_from_this<Material>,
TexturePtr texture(QString key) { return m_textures.value(key); }
// QMap<QString, TexturePtr> in() const { return m_in; }
+ const QMap<QString, MappableValue>& attributeMap() const { return m_attributeMap; }
+ const QMap<QString, MappableValue>& uniformMap() const { return m_uniformMap; }
+
signals:
void changed(MaterialPtr);
@@ -103,6 +153,9 @@ private slots:
QMap<QString, TexturePtr> m_textures;
bool m_prog_binded;
+ QMap<QString, MappableValue> m_attributeMap;
+ QMap<QString, MappableValue> m_uniformMap;
+
ScenePtr m_scene;
};
View
@@ -235,6 +235,8 @@ void Model::render(ObjectPtr o, State& state, const Node& node) {
if (res > 0) state.setPicked(o, m);
}
+
+ state.applyAutoUniforms();
m->render(state);
if (material) state.popMaterial();
View
@@ -121,6 +121,40 @@ class GLProgram : public QObject, public std::enable_shared_from_this<GLProgram>
void setUniform(GLint loc, const Eigen::Vector3f& v) { glRun(glUniform3fv(loc, 1, v.data())); }
void setUniform(GLint loc, const Eigen::Vector4f& v) { glRun(glUniform4fv(loc, 1, v.data())); }
+ void setUniform(GLint loc, const Eigen::Projective3f& m) { glRun(glUniformMatrix4fv(loc, 1, false, m.data())); }
+ void setUniform(GLint loc, const Eigen::Affine3f& m) { glRun(glUniformMatrix3fv(loc, 1, false, m.data())); }
+
+ template <typename T>
+ void setUniform(State* state, QString name, int vector_dimension, const T& t, bool restore = false) {
+ glCheck("setUniform");
+ GLint prog = 0;
+ glRun(glGetIntegerv(GL_CURRENT_PROGRAM, &prog));
+ if (!prog != m_prog)
+ bind(state);
+
+ GLint loc = glRun2(glGetUniformLocation(m_prog, name.toAscii().data()));
+ if(loc == -1) {
+ //Log::error("Failed to query uniform variable %s location", name.toAscii().data());
+ } else {
+ setUniform(loc, vector_dimension, t);
+ }
+
+ // restore the old state
+ if (restore && prog != (GLint)m_prog)
+ glRun(glUseProgram(prog));
+ }
+
+ void setUniform(GLint loc, int vector_dimension, const std::vector<float>& v) {
+ if (vector_dimension == 1)
+ glUniform1fv(loc, v.size(), v.data());
+ else if (vector_dimension == 2)
+ glUniform2fv(loc, v.size()/2, v.data());
+ else if (vector_dimension == 3)
+ glUniform3fv(loc, v.size()/3, v.data());
+ else if (vector_dimension == 4)
+ glUniform4fv(loc, v.size()/4, v.data());
+ else assert(false);
+ }
/// Restore the uniform state stored in list.
void setUniform(UniformVar::List list, bool relocate = true);
Oops, something went wrong.

0 comments on commit 283066f

Please sign in to comment.