00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "materialinstance.h"
00021 #include "material.h"
00022
00023 #include <QtCore/QVariant>
00024 #include <QtGui/QVector2D>
00025 #include <QtGui/QColor>
00026
00027 #include "math.h"
00028 #include "engine.h"
00029 #include "texture.h"
00030 #include "glheaders.h"
00031
00032 REGISTER_OBJECTTYPE( GluonGraphics, MaterialInstance )
00033
00034 using namespace GluonGraphics;
00035
00036 class MaterialInstance::MaterialInstancePrivate
00037 {
00038 public:
00039 MaterialInstancePrivate()
00040 {
00041 bound = false;
00042 }
00043
00044 Material* material;
00045
00046 QHash<QString, int> uniformLocations;
00047 QHash<QString, int> attributeLocations;
00048
00049 QHash<QString, QVariant> uniformValues;
00050
00051 QHash<uint, Texture*> textures;
00052
00053 bool bound;
00054 };
00055
00056 MaterialInstance::MaterialInstance( QObject* parent )
00057 : GluonObject( parent ),
00058 d( new MaterialInstancePrivate )
00059 {
00060 }
00061
00062 MaterialInstance::~MaterialInstance()
00063 {
00064 delete d;
00065 }
00066
00067 void
00068 MaterialInstance::bind()
00069 {
00070 if( !d->material )
00071 return;
00072
00073 glUseProgram( d->material->glProgram() );
00074 d->bound = true;
00075
00076 QList<QByteArray> properties = dynamicPropertyNames();
00077 foreach( QByteArray prop, properties )
00078 {
00079 setGLUniform( prop, property( prop ) );
00080 }
00081 }
00082
00083 void
00084 MaterialInstance::release()
00085 {
00086 glUseProgram( 0 );
00087 d->bound = false;
00088 }
00089
00090 Material*
00091 MaterialInstance::material()
00092 {
00093 return d->material;
00094 }
00095
00096 void
00097 MaterialInstance::setMaterial( Material* material )
00098 {
00099 d->material = material;
00100 }
00101
00102 int MaterialInstance::attributeLocation( const QString& attrib )
00103 {
00104 if( d->attributeLocations.contains( attrib ) )
00105 return d->attributeLocations.value( attrib );
00106
00107 int loc = glGetAttribLocation( d->material->glProgram(), attrib.toUtf8().constData() );
00108 if( loc != -1 )
00109 {
00110 d->attributeLocations.insert( attrib, loc );
00111 }
00112
00113 return loc;
00114 }
00115
00116 int MaterialInstance::uniformLocation( const QString& name )
00117 {
00118 if( d->uniformLocations.contains( name ) )
00119 return d->uniformLocations.value( name );
00120
00121 int loc = glGetUniformLocation( d->material->glProgram(), name.toUtf8().constData() );
00122 if( loc != -1 )
00123 {
00124 d->uniformLocations.insert( name, loc );
00125 }
00126
00127 return loc;
00128 }
00129
00130 void
00131 MaterialInstance::setModelViewProjectionMatrix( QMatrix4x4 mvp )
00132 {
00133 int loc = uniformLocation( "modelViewProj" );
00134
00135 float glMatrix[16];
00136 Math::qmatrixToGLMatrix( mvp, glMatrix );
00137 glUniformMatrix4fv( loc, 1, false, glMatrix );
00138 }
00139
00140 void
00141 MaterialInstance::setPropertiesFromMaterial()
00142 {
00143 QHash<QString, QVariant> uniforms = d->material->uniformList();
00144 for( QHash<QString, QVariant>::iterator pitr = uniforms.begin(); pitr != uniforms.end(); ++pitr )
00145 {
00146 setProperty( pitr.key().toUtf8(), pitr.value() );
00147 }
00148 }
00149
00150 void
00151 MaterialInstance::setGLUniform( const QString& name, const QVariant& value )
00152 {
00153 switch( value.type() )
00154 {
00155 case QVariant::UInt:
00156 case QVariant::Int:
00157 glUniform1i( uniformLocation( name ), value.toInt() );
00158 break;
00159 case QVariant::Double:
00160 glUniform1f( uniformLocation( name ), value.toDouble() );
00161 break;
00162 case QVariant::Color:
00163 {
00164 QColor color = value.value<QColor>();
00165 glUniform4f( uniformLocation( name ), color.red() / 255.f, color.green() / 255.f, color.blue() / 255.f, color.alpha() / 255.f );
00166 break;
00167 }
00168 case QVariant::Vector2D:
00169 {
00170 QVector2D vector = value.value<QVector2D>();
00171 glUniform2f( uniformLocation( name ), vector.x(), vector.y() );
00172 break;
00173 }
00174 case QVariant::Vector3D:
00175 {
00176 QVector3D vector = value.value<QVector3D>();
00177 glUniform3f( uniformLocation( name ), vector.x(), vector.y(), vector.z() );
00178 break;
00179 }
00180 case QVariant::Vector4D:
00181 {
00182 QVector4D vector = value.value<QVector4D>();
00183 glUniform4f( uniformLocation( name ), vector.x(), vector.y(), vector.z(), vector.w() );
00184 break;
00185 }
00186 case QVariant::String:
00187 {
00188 if( name.contains( "texture" ) )
00189 {
00190 GluonGraphics::Texture* texture = GluonGraphics::Engine::instance()->texture( value.toString() );
00191 bindTexture( name, texture );
00192 }
00193 break;
00194 }
00195 case QVariant::UserType:
00196 {
00197 GluonCore::GluonObject* obj = GluonCore::GluonObjectFactory::instance()->wrappedObject( value );
00198 if( obj && name.contains( "texture" ) )
00199 {
00200 GluonGraphics::Texture* texture = GluonGraphics::Engine::instance()->texture( obj->name() );
00201
00202 bindTexture( name, texture );
00203 }
00204 break;
00205 }
00206 default:
00207 break;
00208 }
00209 }
00210
00211 void
00212 MaterialInstance::bindTexture( const QString& name, Texture* tex )
00213 {
00214 if( !tex )
00215 return;
00216
00217 QString uniName = name;
00218 int id = uniName.replace( "texture", "" ).toInt();
00219
00220 glActiveTexture( GL_TEXTURE0 + id );
00221 glBindTexture( GL_TEXTURE_2D, tex->glTexture() );
00222 glUniform1i( uniformLocation( name ), id );
00223 }
00224
00225 #include "materialinstance.moc"