00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "material.h"
00021 #include "materialinstance.h"
00022 #include "technique.h"
00023
00024 #include <QDebug>
00025
00026 #include "glheaders.h"
00027 #include <core/gdlhandler.h>
00028 #include <QFile>
00029 #include <QMetaProperty>
00030 #include "backendcapabilities.h"
00031 #include <qtextcodec.h>
00032 #include <qvarlengtharray.h>
00033 #include <QtOpenGL/QGLShaderProgram>
00034
00035 REGISTER_OBJECTTYPE( GluonGraphics, Material )
00036
00037 using namespace GluonGraphics;
00038
00039 class Material::MaterialPrivate
00040 {
00041 public:
00042 MaterialPrivate() :
00043 vertShader(0),
00044 fragShader(0),
00045 glProgram(0),
00046 program(0)
00047 {
00048 }
00049
00050 QHash<QString, Technique*> techniques;
00051
00052 uint vertShader;
00053 QByteArray vertShaderSource;
00054 uint fragShader;
00055 QByteArray fragShaderSource;
00056 uint glProgram;
00057 QString languageVersion;
00058
00059 QHash<QString, MaterialInstance*> instances;
00060
00061 QGLShaderProgram* program;
00062 };
00063
00064 Material::Material( QObject* parent )
00065 : GluonObject( parent ),
00066 d( new MaterialPrivate )
00067 {
00068 createInstance( "default" );
00069 }
00070
00071 Material::~Material()
00072 {
00073 delete d;
00074 }
00075
00076 bool Material::load( const QUrl& url )
00077 {
00078 if(!url.isValid())
00079 return false;
00080
00081 QFile file(url.toLocalFile());
00082 if(!file.open(QIODevice::ReadOnly))
00083 return false;
00084
00085 QByteArray data = file.readAll();
00086
00087 QList<GluonObject*> objects = GluonCore::GDLHandler::instance()->parseGDL(data, this);
00088 if(objects.count() <= 0)
00089 return false;
00090
00091 GluonCore::GluonObject* obj = objects.at(0);
00092 QList<QByteArray> properties = obj->dynamicPropertyNames();
00093 MaterialInstance* defaultInstance = d->instances.find("default").value();
00094
00095 foreach(QByteArray propertyName, properties)
00096 {
00097 if(propertyName == "vertexShader")
00098 {
00099 d->vertShaderSource = obj->property(propertyName).toByteArray();
00100 }
00101 else if(propertyName == "fragmentShader")
00102 {
00103 d->fragShaderSource = obj->property(propertyName).toByteArray();
00104 }
00105 else if(propertyName == "languageVersion")
00106 {
00107 d->languageVersion = obj->property(propertyName).toString();
00108 }
00109 else
00110 {
00111 defaultInstance->setProperty(propertyName, obj->property(propertyName));
00112 }
00113 }
00114
00115 return true;
00116 }
00117
00118 void Material::build( const QString& name )
00119 {
00120 if( d->glProgram )
00121 return;
00122
00123 if( d->fragShaderSource.isEmpty() || d->vertShaderSource.isEmpty() )
00124 return;
00125
00126 QByteArray vertShaderSource;
00127 QByteArray fragShaderSource;
00128 if( BackendCapabilities::type() == BackendCapabilities::BT_OPENGL )
00129 {
00130 if(d->languageVersion.isEmpty())
00131 {
00132 vertShaderSource.append("#version 110\n");
00133 vertShaderSource.append("#define lowp\n");
00134 vertShaderSource.append("#define mediunmp\n");
00135 vertShaderSource.append("#define highp\n");
00136 }
00137 }
00138 else if(BackendCapabilities::type() == BackendCapabilities::BT_OPENGLES)
00139 {
00140 vertShaderSource.append("#ifndef GL_FRAGMENT_PRECISION_HIGH\n");
00141 vertShaderSource.append("#define highp mediump\n");
00142 vertShaderSource.append("#endif\n");
00143 }
00144
00145 fragShaderSource.append(vertShaderSource);
00146
00147 vertShaderSource.append(d->vertShaderSource);
00148 fragShaderSource.append(d->fragShaderSource);
00149
00150 const char* vertShaderData = vertShaderSource.data();
00151 const char* fragShaderData = fragShaderSource.data();
00152
00153 d->program = new QGLShaderProgram();
00154 d->program->addShaderFromSourceCode(QGLShader::Vertex, vertShaderSource);
00155 d->program->addShaderFromSourceCode(QGLShader::Fragment, fragShaderSource);
00156 d->program->link();
00157
00158 if( !d->program->isLinked() )
00159 {
00160 debug( "An error occured during shader compilation!" );
00161 debug( d->program->log() );
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 }
00202
00203 Technique*
00204 Material::technique( const QString& name ) const
00205 {
00206 return 0;
00207 }
00208
00209 void
00210 Material::addTechnique( Technique* technique )
00211 {
00212
00213 }
00214
00215 void
00216 Material::removeTechnique( const QString& name )
00217 {
00218
00219 }
00220
00221 void
00222 Material::setDefaultTechnique( const QString& name )
00223 {
00224
00225 }
00226
00227 uint
00228 Material::glProgram()
00229 {
00230 if( !d->program )
00231 build();
00232
00233 return d->program->programId();
00234 }
00235
00236 MaterialInstance*
00237 Material::createInstance( const QString& name )
00238 {
00239 MaterialInstance* instance;
00240 if( !d->instances.contains( name ) )
00241 {
00242 instance = new MaterialInstance( this );
00243 instance->setMaterial( this );
00244 d->instances.insert( name, instance );
00245 }
00246 else
00247 {
00248 instance = d->instances.value( name );
00249 }
00250 return instance;
00251 }
00252
00253 MaterialInstance*
00254 Material::instance( const QString& name )
00255 {
00256 if( d->instances.contains( name ) )
00257 return d->instances.value( name );
00258
00259 return 0;
00260 }
00261
00262 QHash< QString, QVariant >
00263 Material::uniformList()
00264 {
00265 QHash<QString, QVariant> uniforms;
00266 uniforms.insert( "materialColor", Qt::white );
00267 uniforms.insert( "texture0", "default" );
00268 return uniforms;
00269 }
00270
00271 #include "material.moc"