Kindfield
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Friends Pages
Public Member Functions | Protected Member Functions | List of all members
VolumeShaderProgramEffect Class Reference

#include <volumeeffect_p.h>

Inheritance diagram for VolumeShaderProgramEffect:
Inheritance graph
[legend]
Collaboration diagram for VolumeShaderProgramEffect:
Collaboration graph
[legend]

Public Member Functions

 VolumeShaderProgramEffect (VolumeShaderProgram *parent)
 
virtual ~VolumeShaderProgramEffect ()
 
bool create (const QString &vertexShader, const QString &fragmentShader)
 
void update (QGLPainter *painter, QGLPainter::Updates updates)
 
bool setUniformForPropertyIndex (int propertyIndex, QGLPainter *painter)
 
void setPropertiesDirty ()
 
void setPropertyDirty (int property)
 
void setAttributeFields (QGL::VertexAttribute fields)
 

Protected Member Functions

void processTextureUrl (int uniformLocation, QString urlString)
 
void afterLink ()
 
bool beforeLink ()
 

Detailed Description

Definition at line 106 of file volumeeffect_p.h.

Constructor & Destructor Documentation

VolumeShaderProgramEffect::VolumeShaderProgramEffect ( VolumeShaderProgram parent)

Definition at line 240 of file volumeeffect.cpp.

241 {
242  this->parent = parent;
243  nextTextureUnit = 1;
244  propertyListener = new VolumeShaderProgramPropertyListenerEx(parent, this);
245 }
VolumeShaderProgramEffect::~VolumeShaderProgramEffect ( )
virtual

Definition at line 252 of file volumeeffect.cpp.

253 {
254  QList<QGLTexture2D*> textures = texture2Ds.values();
255  QGLTexture2D* texture;
256  foreach (texture, textures)
257  delete texture;
258 }

Member Function Documentation

void VolumeShaderProgramEffect::afterLink ( )
protected

Definition at line 286 of file volumeeffect.cpp.

287 {
288  // Texture3D stuff
289 // qDebug() << "After link!";
290 // qDebug() << program()->uniformLocation("myTexture3D");
291  m_texture3DuniformValue = program()->uniformLocation("myTexture3D");
292  m_eyePositionUniformLocation = program()->uniformLocation("ve_eyePosition");
293 // qDebug() << m_eyePositionUniformLocation;
294 // qDebug() << "Attribute: " << program()->attributeLocation("multiTexCoord3D");
295 // double data[24];
296 // QGLAttributeValue value(3, GL_FLOAT, 0, array.)
297 // glTexCoordPointer(value.tupleSize(), value.type(),
298 // value.stride(), value.data());
299 
300  GLuint g_volTexObj;
301  GLuint *data = parent.data()->texture3Ddata().data;
302  GLuint w = parent.data()->texture3Ddata().width;
303  GLuint h = parent.data()->texture3Ddata().height;
304  GLuint d = parent.data()->texture3Ddata().depth;
305 // qDebug() << "w " << w << " " << h << " " << d;
306 
307  glGenTextures(1, &g_volTexObj);
308  // bind 3D texture target
309  glBindTexture(GL_TEXTURE_3D, g_volTexObj);
310  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
311  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
312  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
313  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
314  glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
315  // pixel transfer happens here from client to OpenGL server
316  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
317  glTexImage3D(GL_TEXTURE_3D, 0, GL_INTENSITY, w, h, d, 0, GL_LUMINANCE, GL_UNSIGNED_INT, data);
318 
319  program()->setUniformValue(m_texture3DuniformValue, g_volTexObj);
320  // End Texture3D stuff
321 
322  propertyIdsToUniformLocations.clear();
323  uniformLocationsToTextureUnits.clear();
324  nextTextureUnit = 1;
325  propertyListener->disconnect();
326  if (parent.data() == 0)
327  {
328  return;
329  }
330  QObject::connect(propertyListener, SIGNAL(propertyChanged()), parent.data(), SIGNAL(effectChanged()));
331 
332  const QMetaObject* parentMetaObject = parent.data()->metaObject();
333  int parentMethodCount = parentMetaObject->methodCount();
334 
335  for (int i = parentMetaObject->propertyOffset();
336  i < parentMetaObject->propertyCount(); i++)
337  {
338  QMetaProperty metaProperty = parentMetaObject->property(i);
339  QByteArray propertyName = metaProperty.name();
340  int location = program()->uniformLocation(propertyName);
341  // -1 indicates that the program does not use the variable,
342  // so ignore those variables.
343  if (location != -1)
344  {
345  dirtyProperties.append(i);
346  propertyIdsToUniformLocations[i] = location;
347  if (metaProperty.hasNotifySignal())
348  {
349  QMetaMethod notifySignal = metaProperty.notifySignal();
350 
351  int signalIndex = notifySignal.methodIndex();
352 
353  // Connect the myFooChanged() signal from the VolumeShaderProgram
354  // to the corresponding imaginary slot on the listener
355  // Use the method count to make sure that we don't stomp on
356  // real methods and add the property index to tell the
357  // properties apart.
358  // Warning: Subclasses of VolumeShaderProgramPropertyListener will
359  // generate spurious property updates and lots of warnings
360  // and might even crash
361  QMetaObject::connect(parent.data(), signalIndex,
362  propertyListener, parentMethodCount + i);
363  } else {
364  qWarning() << "Warning: No notification signal found for property: " << propertyName;
365  propertiesWithoutNotificationSignal.append(i);
366  }
367  }
368  }
369 
370  // Refresh everything
371  this->setPropertiesDirty();
372 }
bool VolumeShaderProgramEffect::beforeLink ( )
protected

Definition at line 374 of file volumeeffect.cpp.

375 {
376 // program()->bindAttributeLocation("multiTexCoord3D", 8);
377  return true;
378 }
bool VolumeShaderProgramEffect::create ( const QString &  vertexShader,
const QString &  fragmentShader 
)

Definition at line 270 of file volumeeffect.cpp.

271 {
272  if (!QOpenGLShaderProgram::hasOpenGLShaderPrograms())
273  return false;
274 
275  setVertexShader(vertexShader.toLatin1());
276  setFragmentShader(fragmentShader.toLatin1());
277 
278  return true;
279 }
void VolumeShaderProgramEffect::processTextureUrl ( int  uniformLocation,
QString  urlString 
)
protected

Definition at line 665 of file volumeeffect.cpp.

666 {
667  QUrl url(urlString);
668  if (urlString.isEmpty() &&
669  urls.contains(uniformLocation) &&
670  !urls[uniformLocation].isNull())
671  {
672  if (images.contains(uniformLocation) && !images[uniformLocation].isNull())
673  {
674  images[uniformLocation] = QImage();
675  urls.remove(uniformLocation);
676  changedTextures.insert(uniformLocation);
677  return;
678  }
679  };
680 
681  // Try to make path absolute:
682  if (url.isRelative())
683  {
684  // Get the baseUrl from the qml engine
685  QQmlContext *context =
686  QQmlEngine::contextForObject(parent.data());
687 
688  if (context)
689  {
690  QUrl baseurl = context->baseUrl();
691  QUrl absolute = baseurl.resolved(urlString);
692 
693  if (absolute.isValid())
694  {
695  url = absolute;
696  urlString = absolute.toString();
697  } else {
698  qWarning() << "Warning: failed to resolve relative path " <<
699  urlString;
700  }
701  }
702  };
703 
704  if (urlString != urls[uniformLocation])
705  {
706  if (url.scheme() != QLatin1String("file"))
707  {
708  // TODO - support network URL's for loading - note that this feature is for
709  // the Qt3D 1.1 release and there is no point in implementing it until for example
710  // model loading and all other parts of Qt3D support it. Also when it is implemented
711  // it has to be done with a facility that does not depend on private headers in
712  // QtQml which can change within minor dot-point releases.
713  qWarning("Network URL's not yet supported - %s", qPrintable(urlString));
714  }
715  else
716  {
717  QString localFile = url.toLocalFile();
718  if (localFile.endsWith(QLatin1String(".dds")))
719  {
720  qWarning("Shader effects with compressed textures not supported: %s",
721  qPrintable(urlString));
722  }
723  else
724  {
725  QImage im(localFile);
726  if (im.isNull())
727  {
728  qWarning("Could not load image from local file path - %s", qPrintable(localFile));
729  }
730  else
731  {
732  images[uniformLocation] = im;
733  changedTextures.insert(uniformLocation);
734  }
735  }
736  }
737  }
738 }
void VolumeShaderProgramEffect::setAttributeFields ( QGL::VertexAttribute  fields)
void VolumeShaderProgramEffect::setPropertiesDirty ( )

Definition at line 641 of file volumeeffect.cpp.

642 {
643  dirtyProperties = this->propertyIdsToUniformLocations.keys();
644 }
void VolumeShaderProgramEffect::setPropertyDirty ( int  property)

Definition at line 650 of file volumeeffect.cpp.

651 {
652  if (dirtyProperties.indexOf(property) == -1)
653  {
654  dirtyProperties.append(property);
655  }
656 }
bool VolumeShaderProgramEffect::setUniformForPropertyIndex ( int  propertyIndex,
QGLPainter *  painter 
)
inline

Definition at line 515 of file volumeeffect.cpp.

516 {
517  QOpenGLShaderProgram *program = this->program();
518  int uniformLocation = propertyIdsToUniformLocations[propertyIndex];
519 
520  QVariant value =
521  parent.data()->metaObject()->property(propertyIndex).read(parent.data());
522 
523  switch(int(value.type()))
524  {
525  case QVariant::Double:
526  // Convert double to float to pass to shader program
527  case QMetaType::Float:
528  program->setUniformValue(uniformLocation, value.toFloat());
529  break;
530  case QVariant::Int:
531  program->setUniformValue(uniformLocation, value.toInt());
532  break;
533  case QVariant::UInt:
534  program->setUniformValue(uniformLocation, value.toUInt());
535  break;
536  case QVariant::Bool:
537  program->setUniformValue(uniformLocation, value.toBool());
538  break;
539  case QVariant::Color:
540  program->setUniformValue(uniformLocation, value.value<QColor>());
541  break;
542  case QVariant::List:
543  setUniformFromFloatList(program, uniformLocation, value.toList());
544  break;
545  case QVariant::Point:
546  program->setUniformValue(uniformLocation, value.toPoint());
547  break;
548  case QVariant::PointF:
549  program->setUniformValue(uniformLocation, value.toPointF());
550  break;
551  case QVariant::Size:
552  program->setUniformValue(uniformLocation, value.toSize());
553  break;
554  case QVariant::SizeF:
555  program->setUniformValue(uniformLocation, value.toSizeF());
556  break;
557  case QVariant::Matrix4x4:
558  program->setUniformValue(uniformLocation, value.value<QMatrix4x4>());
559  break;
560  case QVariant::Vector2D:
561  program->setUniformValue(uniformLocation, value.value<QVector2D>());
562  break;
563  case QVariant::Vector3D:
564  program->setUniformValue(uniformLocation, value.value<QVector3D>());
565  break;
566  case QVariant::Vector4D:
567  program->setUniformValue(uniformLocation, value.value<QVector4D>());
568  break;
569  case QVariant::String:
570  {
571  // We assume strings are URLs to images for textures
572  QString urlString = value.toString();
573  processTextureUrl(uniformLocation, urlString);
574  }
575  break;
576  case QVariant::Image:
577  {
578  QImage image(value.toString());
579  setUniform(uniformLocation, image, painter);
580  }
581  break;
582  default:
583  qWarning() << "Unrecognized variant for property " << parent.data()->metaObject()->property(propertyIndex).name() << " of type " << value.typeName() << ", could not set corresponding shader variable";
584  }
585  return true;
586 }
void VolumeShaderProgramEffect::update ( QGLPainter *  painter,
QGLPainter::Updates  updates 
)

Definition at line 441 of file volumeeffect.cpp.

442 {
443 // painter->glActiveTexture(GL_TEXTURE0 + 0);
444 // program()->setUniformValue(m_eyeLocation, painter->);
445 
446  if (changedTextures.count() > 0)
447  {
448  foreach (int i, changedTextures)
449  {
450  if (!images.contains(i))
451  {
452  changedTextures.remove(i);
453  continue;
454  }
455 
456  if (!images[i].isNull())
457  {
458  setUniform(i, images[i], painter);
459  } else
460  {
461  qWarning() << "Warning: VolumeShaderProgramEffect failed to apply texture for uniform" << i << (urls.contains(i) ? QLatin1String(" url: ") + urls[i] : QString());
462  }
463  changedTextures.remove(i);
464  }
465  }
466 
467  // Update the standard uniform variables.
468  QGLShaderProgramEffect::update(painter, updates);
469 
470  // Assign custom properties if they exist
471  if (!parent.data() || !(propertyIdsToUniformLocations.count() > 0))
472  return;
473 
474  // update dirty properties and remove them from the list
475  int propertyIndex;
476  QList<int> propertiesNotUpdated;
477  foreach (propertyIndex, dirtyProperties)
478  {
479  if (!setUniformForPropertyIndex(propertyIndex, painter))
480  {
481  propertiesNotUpdated.append(propertyIndex);
482  };
483  }
484  dirtyProperties.clear();
485  dirtyProperties.append(propertiesNotUpdated);
486 
487  // always update the properties we can't track
488  foreach (propertyIndex, propertiesWithoutNotificationSignal)
489  {
490  setUniformForPropertyIndex(propertyIndex, painter);
491  }
492 
493  // Added specifically for the volume shader effect.
494  // This could have been passed more directly, but since we need to
495  // know about the scaling, translation and rotation of the item,
496  // we might as well calculate the inverse of the modelView matrix
497  // to get the true eye position.
498  // TODO: For better performance: Intercept the setCamera action in QGLPainter
499  // and calculate the proper eye position while calculating the matrices.
500  QVector4D inverseColumn3 = painter->modelViewMatrix().top().inverted().column(3);
501  program()->setUniformValue(m_eyePositionUniformLocation, inverseColumn3);
502 }

The documentation for this class was generated from the following files: