summaryrefslogtreecommitdiffstats
path: root/src/imports/threed/shaderprogram.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/imports/threed/shaderprogram.cpp')
-rw-r--r--src/imports/threed/shaderprogram.cpp979
1 files changed, 0 insertions, 979 deletions
diff --git a/src/imports/threed/shaderprogram.cpp b/src/imports/threed/shaderprogram.cpp
deleted file mode 100644
index 7b775b5b..00000000
--- a/src/imports/threed/shaderprogram.cpp
+++ /dev/null
@@ -1,979 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation ([email protected])
-**
-** This file is part of the QtQuick3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "shaderprogram.h"
-#include "shaderprogram_p.h"
-#include "qglabstracteffect.h"
-#include <QtOpenGL/qglshaderprogram.h>
-#include <QWeakPointer>
-
-#include <QDeclarativeEngine>
-#include <QDeclarativeContext>
-#include <QFile>
-
-#include "qglscenenode.h"
-/*!
- \qmlclass ShaderProgram ShaderProgram
- \brief The ShaderProgram item is derivative class of the more general Effect class in QML/3d.
- Whereas the Effect class provides support for standard effects under OpenGL, the ShaderProgramEffect supports effects based on custom shader programs for the GPU.
- \since 4.8
- \ingroup qt3d::qml3d
- \inherits Effect
-
- The ShaderProgram class provides Qml/3d users with the ability to use a QGLShaderProgram within the
- logical context of the normal \l Effect class provided by Qml/3d.
-
- If the system does not support shaders, then ShaderProgram will
- behave the same as \l Effect, with support for simple lit
- materials only.
-
- \section1 Attributes
-
- ShaderProgram provides a standard set of 8 vertex attributes that
- can be provided via the geometry \l Mesh:
-
- \table
- \header \o Shader Variable \o Mesh Attribute \o Purpose
- \row \o \c qt_Vertex \o QGL::Position
- \o The primary position of the vertex.
- \row \o \c qt_Normal \o QGL::Normal
- \o The normal at each vertex, for lit material effects.
- \row \o \c qt_Color \o QGL::Color
- \o The color at each vertex, for per-vertex color effects.
- \row \o \c qt_MultiTexCoord0 \o QGL::TextureCoord0
- \o The texture co-ordinate at each vertex for texture unit 0.
- \row \o \c qt_MultiTexCoord1 \o QGL::TextureCoord1
- \o Secondary texture co-ordinate at each vertex.
- \row \o \c qt_MultiTexCoord2 \o QGL::TextureCoord2
- \o Tertiary texture co-ordinate at each vertex.
- \row \o \c qt_Custom0 \o QGL::CustomVertex0
- \o First custom vertex attribute that can be used for any
- user-defined purpose.
- \row \o \c qt_Custom1 \o QGL::CustomVertex1
- \o Second custom vertex attribute that can be used for any
- user-defined purpose.
- \endtable
-
- These attributes are used in the vertexShader, as in the following
- example of a simple texture shader:
-
- \code
- attribute highp vec4 qt_Vertex;
- attribute highp vec4 qt_MultiTexCoord0;
- uniform mediump mat4 qt_ModelViewProjectionMatrix;
- varying highp vec4 texCoord;
-
- void main(void)
- {
- gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
- texCoord = qt_MultiTexCoord0;
- }
- \endcode
-
- \section1 Standard uniform variables
-
- ShaderProgram provides a standard set of uniform variables for
- common values from the environment:
-
- \table
- \header \o Shader Variable \o Purpose
- \row \o \c qt_ModelViewProjectionMatrix
- \o Combination of the modelview and projection matrices into a
- single 4x4 matrix.
- \row \o \c qt_ModelViewMatrix
- \o Modelview matrix without the projection. This is typically
- used for performing calculations in eye co-ordinates.
- \row \o \c qt_ProjectionMatrix
- \o Projection matrix without the modelview.
- \row \o \c qt_NormalMatrix
- \o Normal matrix, which is the transpose of the inverse of the
- top-left 3x3 part of the modelview matrix. This is typically
- used in lighting calcuations to transform \c qt_Normal.
- \row \o \c qt_WorldMatrix
- \o Modelview matrix without the eye position and orientation
- component. See QGLPainter::worldMatrix() for further
- information.
- \row \o \c qt_Texture0
- \o Sampler holding the texture from the Effect::texture property.
- \row \o \c qt_Color
- \o Set to the value of the Effect::color property.
- \endtable
-
- The above variables are usually declared in the shaders as follows
- (where \c highp may be replaced with \c mediump or \c lowp depending
- upon the shader's precision requirements):
-
- \code
- uniform highp mat4 qt_ModelViewProjectionMatrix;
- uniform highp mat4 qt_ModelViewMatrix;
- uniform highp mat3 qt_NormalMatrix;
- uniform sampler2D qt_Texture0;
- uniform highp vec4 qt_Color;
- \endcode
-
- Other lighting and material values, such as the ambient, diffuse,
- and specular colors, can be passed to the shader program using
- custom uniform variables, or the standard variable names described
- in the QGLShaderProgramEffect documentation.
-
- \section1 Custom uniform variables
-
- Many properties defined on the ShaderProgram are automatically exposed as
- uniforms for the fragment and vertex shaders under the same name.
-
- QML and shader types do not match exactly, so the following table shows
- how QML properties should be declared in qml compared to shader programs:
-
- \table
- \header \o QML Property \o Shader Program Variable
-\row \o \code property double myDouble : 1.0 \endcode \o uniform highp float myDouble;
- \row \o \code property real myReal : 1.0 \endcode \o uniform mediump float myReal;
- \row \o \code property bool myBoolean : true \endcode \o uniform bool myBoolean;
- \row \o \code property int myInt : 1 \endcode \o uniform int myInt;
- \row \o \code property variant myPoint : Qt.point(1, 1) \endcode \o uniform mediump vec2 myPoint;
- \row \o \code property variant myPointF : Qt.point(1.0, 1.0) \endcode \o uniform mediump vec2 myPointF;
- \row \o \code property variant mySize : Qt.size(1.0, 1.0) \endcode \o uniform mediump vec2 mySize;
- \row \o \code property color myColor : "#80c342" \endcode \o uniform lowp vec4 myColor;
- \row \o \code property variant myMatrix3x3 :
- [1.0, 0.0, 0.0,
- 0.0, 1.0, 0.0,
- 0.0, 0.0, 1.0] \endcode \o uniform mat3 myMatrix3x3;
- \row \o \code property variant myMatrix4x4 :
- [1.0 , 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0 ]\endcode \o uniform mat4 myMatrix4x4;
- \row \o \code property string imageExample :
- "http://example.com/image.png" \endcode \o uniform sampler2D imageExample;
- \endtable
-
- Note: The precision hints in this table are just examples. highp,
- mediump, and lowp do not map directly onto floats, doubles, colors etc.
- Choose the most appropriate variable type for your qml or javascript, and
- the most appropriate precision for your shader program.
-
- Be aware that variant properties in general and matrices in particular
- can have significant performance implications. Conversion from variants
- can be slow, and matrices can consume multiple slots for uniforms, which
- are usually limited by hardware.
-
- String properties are assumed to be urls to images for use in textures.
- Where these images are remote, they are loaded in the background and bound
- to the effect when they are ready.
- \sa QGLGraphicsViewportItem
-*/
-
-class ShaderProgramEffect;
-QT_BEGIN_NAMESPACE
-
-class ShaderProgramPrivate
-{
-public:
- ShaderProgramPrivate()
- : regenerate(false)
- , shadersSupported(true) // Assume supported until known otherwise.
- , effect(0)
- {
- }
-
- QString vertexShader;
- QString fragmentShader;
- QUrl vertexShaderSource;
- QUrl fragmentShaderSource;
- bool regenerate;
- bool shadersSupported;
- ShaderProgramEffect *effect;
-};
-
-
-/*
- \internal
- Construction for the ShaderProgramEffect class consists of setting the key parameter values of the
- class to undefined. As such, a shader program effect with no further initialisation will do nothing at all
- until further creation of shader programs for it has been carried out.
-*/
-ShaderProgramEffect::ShaderProgramEffect(ShaderProgram* parent)
-{
- this->parent = parent;
- nextTextureUnit = 1;
- propertyListener = new ShaderProgramPropertyListenerEx(parent, this);
-}
-
-/*
- \internal
- Destruction entails deletion of the underlying \l QGLShaderProgram which forms the functional core of the
- class.
-*/
-ShaderProgramEffect::~ShaderProgramEffect()
-{
- QList<QGLTexture2D*> textures = texture2Ds.values();
- QGLTexture2D* texture;
- foreach (texture, textures)
- delete texture;
-}
-
-/*
- \internal
- The act of shader programe creation can be undertakn in the manner defined for the QGLShaderProgram class.
- Failure to successfully carry out creation will result in a warning message. Success will auto-populate the
- parameter fields of the ShaderProgramEffect with the necessary values based on the shader program.
-
- The vertex shader source is defined as a QString in the \a vertexShader parameter, while the fragment shader
- is provided in the \a fragmentShader parameter.
-*/
-bool ShaderProgramEffect::create
- (const QString& vertexShader, const QString& fragmentShader)
-{
- if (!QGLShaderProgram::hasOpenGLShaderPrograms())
- return false;
-
- setVertexShader(vertexShader.toLatin1());
- setFragmentShader(fragmentShader.toLatin1());
-
- return true;
-}
-
-/*!
- \internal
- Convenience function to setup the relationship between object properties
- and shader uniforms for later use.
- */
-void ShaderProgramEffect::afterLink()
-{
- propertyIdsToUniformLocations.clear();
- uniformLocationsToTextureUnits.clear();
- nextTextureUnit = 1;
- propertyListener->disconnect();
- if (parent.data() == 0)
- {
- return;
- }
- QObject::connect(propertyListener, SIGNAL(propertyChanged()), parent.data(), SIGNAL(effectChanged()));
-
- const QMetaObject* parentMetaObject = parent.data()->metaObject();
- int parentMethodCount = parentMetaObject->methodCount();
-
- for (int i = parentMetaObject->propertyOffset();
- i < parentMetaObject->propertyCount(); i++)
- {
- QMetaProperty metaProperty = parentMetaObject->property(i);
- QByteArray propertyName = metaProperty.name();
- int location = program()->uniformLocation(propertyName);
- // -1 indicates that the program does not use the variable,
- // so ignore those variables.
- if (location != -1)
- {
- dirtyProperties.append(i);
- propertyIdsToUniformLocations[i] = location;
- if (metaProperty.hasNotifySignal())
- {
- QMetaMethod notifySignal = metaProperty.notifySignal();
-
- int signalIndex = notifySignal.methodIndex();
-
- // Connect the myFooChanged() signal from the ShaderProgram
- // to the corresponding imaginary slot on the listener
- // Use the method count to make sure that we don't stomp on
- // real methods and add the property index to tell the
- // properties apart.
- // Warning: Subclasses of ShaderProgramPropertyListener will
- // generate spurious property updates and lots of warnings
- // and might even crash
- QMetaObject::connect(parent.data(), signalIndex,
- propertyListener, parentMethodCount + i);
- } else {
- qWarning() << "Warning: No notification signal found for property: " << propertyName;
- propertiesWithoutNotificationSignal.append(i);
- }
- }
- }
-
- // Refresh everything
- this->setPropertiesDirty();
-}
-
-/*!
- \internal
- Precondition: list is a list of floats
- */
-static inline void setUniformFromFloatList(QGLShaderProgram *program, int uniformLocation, QList<QVariant> list)
-{
- switch(list.length())
- {
- case 1:
- program->setUniformValue(uniformLocation, list.at(0).toFloat());
- break;
- case 2:
- program->setUniformValue(uniformLocation,
- list.at(0).toFloat(),
- list.at(1).toFloat());
- break;
- case 3:
- program->setUniformValue(uniformLocation,
- list.at(0).toFloat(),
- list.at(1).toFloat(),
- list.at(2).toFloat());
- break;
- case 4:
- program->setUniformValue(uniformLocation,
- list.at(0).toFloat(),
- list.at(1).toFloat(),
- list.at(2).toFloat(),
- list.at(3).toFloat());
- break;
- case 9:
- {
- QMatrix3x3 matrix;
- for (int i = 0; i < 9; i++)
- {
- matrix(i / 3, i % 3) = list.at(i).toFloat();
- }
- program->setUniformValue(uniformLocation, matrix);
- }
- break;
- case 16:
- {
- QMatrix4x4 matrix;
- for (int i = 0; i < 16; i++)
- {
- matrix( i / 4, i % 4) = list.at(i).toFloat();
- }
- program->setUniformValue(uniformLocation, matrix);
- }
- break;
- default:
- // Very little information available to make this warning any more helpful
- qWarning() << "Warning: unexpected list size: " << list.size() << ", only 1-4, 9 and 16 supported";
- }
-}
-
-/*!
- \internal
- This performs all updates for the shader program given a QGLPainter \a painter, and the type of update
- being carried out based on the \a updates field, which is an enumeration of the possible painter updates.
-*/
-void ShaderProgramEffect::update
- (QGLPainter *painter, QGLPainter::Updates updates)
-{
- if (changedTextures.count() > 0)
- {
- foreach (int i, changedTextures)
- {
- if (!images.contains(i))
- {
- changedTextures.remove(i);
- continue;
- }
-
- if (!images[i].isNull())
- {
- setUniform(i, images[i], painter);
- } else
- {
- qWarning() << "Warning: ShaderProgramEffect failed to apply texture for uniform" << i << (urls.contains(i) ? QLatin1String(" url: ") + urls[i] : QString());
- }
- changedTextures.remove(i);
- }
- }
-
- // Update the standard uniform variables.
- QGLShaderProgramEffect::update(painter, updates);
-
- // Assign custom properties if they exist
- if (!parent.data() || !(propertyIdsToUniformLocations.count() > 0))
- return;
-
- // update dirty properties and remove them from the list
- int propertyIndex;
- QList<int> propertiesNotUpdated;
- foreach (propertyIndex, dirtyProperties)
- {
- if (!setUniformForPropertyIndex(propertyIndex, painter))
- {
- propertiesNotUpdated.append(propertyIndex);
- };
- }
- dirtyProperties.clear();
- dirtyProperties.append(propertiesNotUpdated);
-
- // always update the properties we can't track
- foreach (propertyIndex, propertiesWithoutNotificationSignal)
- {
- setUniformForPropertyIndex(propertyIndex, painter);
- }
-}
-
-inline QGLTexture2D* ShaderProgramEffect::textureForUniformValue(int uniformLocation)
-{
- QGLTexture2D* result = texture2Ds.value(uniformLocation);
- if (result == 0)
- {
- result = new QGLTexture2D();
- texture2Ds[uniformLocation] = result;
- }
- return result;
-}
-
-inline bool ShaderProgramEffect::setUniformForPropertyIndex(int propertyIndex, QGLPainter *painter)
-{
- QGLShaderProgram *program = this->program();
- int uniformLocation = propertyIdsToUniformLocations[propertyIndex];
-
- QVariant value =
- parent.data()->metaObject()->property(propertyIndex).read(parent.data());
-
- switch(value.type())
- {
- case QVariant::Double:
- // Convert double to float to pass to shader program
- case QMetaType::Float:
- program->setUniformValue(uniformLocation, value.toFloat());
- break;
- case QVariant::Int:
- program->setUniformValue(uniformLocation, value.toInt());
- break;
- case QVariant::UInt:
- program->setUniformValue(uniformLocation, value.toUInt());
- break;
- case QVariant::Bool:
- program->setUniformValue(uniformLocation, value.toBool());
- break;
- case QVariant::Color:
- program->setUniformValue(uniformLocation, value.value<QColor>());
- break;
- case QVariant::List:
- setUniformFromFloatList(program, uniformLocation, value.toList());
- break;
- case QVariant::Point:
- program->setUniformValue(uniformLocation, value.toPoint());
- break;
- case QVariant::PointF:
- program->setUniformValue(uniformLocation, value.toPointF());
- break;
- case QVariant::Size:
- program->setUniformValue(uniformLocation, value.toSize());
- break;
- case QVariant::SizeF:
- program->setUniformValue(uniformLocation, value.toSizeF());
- break;
- case QVariant::Matrix4x4:
- program->setUniformValue(uniformLocation, value.value<QMatrix4x4>());
- break;
- case QVariant::Vector2D:
- program->setUniformValue(uniformLocation, value.value<QVector2D>());
- break;
- case QVariant::Vector3D:
- program->setUniformValue(uniformLocation, value.value<QVector3D>());
- break;
- case QVariant::Vector4D:
- program->setUniformValue(uniformLocation, value.value<QVector4D>());
- break;
- case QVariant::String:
- {
- // We assume strings are URLs to images for textures
- QString urlString = value.toString();
- processTextureUrl(uniformLocation, urlString);
- }
- break;
- case QVariant::Image:
- {
- QImage image(value.toString());
- setUniform(uniformLocation, image, painter);
- }
- break;
- default:
- qWarning() << "Unrecognized variant for property " << parent.data()->metaObject()->property(propertyIndex).name() << " of type " << value.typeName() << ", could not set corresponding shader variable";
- }
- return true;
-}
-
-/*!
- \internal Helper function for applying a \a pixmap to a texture for a shader program. This function should be called from within update() in order to have access to the right GL context through the \a painter.
- */
-void ShaderProgramEffect::setUniform
- (int uniformLocation, const QPixmap pixmap, QGLPainter* painter)
-{
- // TODO: Perspective correction
- QGLTexture2D* texture = textureForUniformValue(uniformLocation);
- int unit = textureUnitForUniformValue(uniformLocation);
- if (texture != 0)
- {
- texture->setPixmap(pixmap);
- painter->glActiveTexture(GL_TEXTURE0 + unit);
- texture->bind();
- program()->setUniformValue(uniformLocation, unit);
- }
-}
-
-/*!
- \internal Helper function for applying an \a images to a texture for a shader program. This function should be called from within update() in order to have access to the right GL context through the \a painter.
- */
-void ShaderProgramEffect::setUniform
- (int uniformLocation, const QImage& image, QGLPainter* painter)
-{
- // TODO: Perspective correction
- QGLTexture2D* texture = textureForUniformValue(uniformLocation);
- int unit = textureUnitForUniformValue(uniformLocation);
- if (texture != 0)
- {
- texture->setImage(image);
- painter->glActiveTexture(GL_TEXTURE0 + unit);
- texture->bind();
- program()->setUniformValue(uniformLocation, unit);
- }
-}
-
-/*!
- \internal Find the texture unit to associate with \a uniformLocation.
-*/
-int ShaderProgramEffect::textureUnitForUniformValue(int uniformLocation)
-{
- int unit = uniformLocationsToTextureUnits.value(uniformLocation, -1);
- if (unit == -1) {
- unit = nextTextureUnit++;
- uniformLocationsToTextureUnits[uniformLocation] = unit;
- }
- return unit;
-}
-
-/*!
- \internal set all properties dirty so they are reuploaded
- next update()
- */
-void ShaderProgramEffect::setPropertiesDirty()
-{
- dirtyProperties = this->propertyIdsToUniformLocations.keys();
-}
-
-/*!
- \internal Set a specific property as dirty so that it is reuploaded
- next update()
- */
-void ShaderProgramEffect::setPropertyDirty(int property)
-{
- if (dirtyProperties.indexOf(property) == -1)
- {
- dirtyProperties.append(property);
- }
-}
-
-/*!
- \internal Update the image for the texture bound at \a uniform location with
- the the image at \a urlString. If \a urlString is a remote resource, this
- starts an asycnrounous loading process.
-
- Note: Consecutive calls with the same url for a given uniform are ignored.
-*/
-void ShaderProgramEffect::processTextureUrl(int uniformLocation, QString urlString)
-{
- QUrl url(http://code.qt.io/urlString);
- if (urlString.isEmpty() &&
- urls.contains(uniformLocation) &&
- !urls[uniformLocation].isNull())
- {
- if (images.contains(uniformLocation) && !images[uniformLocation].isNull())
- {
- images[uniformLocation] = QImage();
- urls.remove(uniformLocation);
- changedTextures.insert(uniformLocation);
- return;
- }
- };
-
- bool async = true;
- // Try to make path absolute:
- if (url.isRelative())
- {
- async = false;
- // Get the baseUrl from the declarative engine
- QDeclarativeContext *context =
- QDeclarativeEngine::contextForObject(parent.data());
-
- if (context)
- {
- QUrl baseurl = context->baseUrl();
- QUrl absolute = baseurl.resolved(urlString);
-
- if (absolute.isValid())
- {
- url = absolute;
- urlString = absolute.toString();
- } else {
- qWarning() << "Warning: failed to resolve relative path " <<
- urlString;
- }
- }
- };
-
- if (urlString != urls[uniformLocation])
- {
- if (url.scheme() != QLatin1String("file"))
- {
- // TODO - support network URL's for loading - note that this feature is for
- // the Qt3D 1.1 release and there is no point in implementing it until for example
- // model loading and all other parts of Qt3D support it. Also when it is implemented
- // it has to be done with a facility that does not depend on private headers in
- // QtDeclarative which can change within minor dot-point releases.
- qWarning("Network URL's not yet supported - %s", qPrintable(urlString));
- }
- else
- {
- QString localFile = url.toLocalFile();
- if (localFile.endsWith(QLatin1String(".dds")))
- {
- qWarning("Shader effects with compressed textures not supported: %s",
- qPrintable(urlString));
- }
- else
- {
- QImage im(localFile);
- if (im.isNull())
- {
- qWarning("Could not load image from local file path - %s", qPrintable(localFile));
- }
- else
- {
- images[uniformLocation] = im;
- changedTextures.insert(uniformLocation);
- }
- }
- }
- }
-}
-
-/*!
- \internal
- Construction of the shader program and assignment of its \a parent object.
-*/
-ShaderProgram::ShaderProgram(QObject *parent)
- : QDeclarativeEffect(parent)
-{
- d = new ShaderProgramPrivate();
-}
-
-/*!
- \internal
- Destruction of the ShaderProgram entails deletion of private data, and explicit deletion of the
- underlying ShaderProgramEffect defined by the class.
-*/
-ShaderProgram::~ShaderProgram()
-{
- delete d->effect;
- delete d;
-}
-
-/*!
- \qmlproperty string ShaderProgram::vertexShader
-
- This property defines the source for the vertex shader to be implemented by this
- instance of the ShaderProgram. This property and the vertexShaderSource()
- property both effect the same underlying object, so setting one will override
- the other.
-
- \sa fragmentShader, vertexShaderSource
-*/
-QString ShaderProgram::vertexShader() const
-{
- return d->vertexShader;
-}
-
-void ShaderProgram::setVertexShader(const QString& value)
-{
- if (!d->vertexShaderSource.isEmpty() || value != d->vertexShader)
- {
- d->vertexShader = value;
- d->regenerate = true;
- d->vertexShaderSource = QUrl();
- emit shaderChanged();
- emit effectChanged();
- }
-}
-
-/*!
- \qmlproperty string ShaderProgram::fragmentShader
- This property defines the source for the fragment shader (ie. pixel shader) to be
- implemented by this instance of the ShaderProgram. This property and the
- fragmentShaderSource() property both effect the same underlying object, so
- setting one will override the other.
-
- \sa vertexShader, fragmentShaderSource
-*/
-QString ShaderProgram::fragmentShader() const
-{
- return d->fragmentShader;
-}
-
-void ShaderProgram::setFragmentShader(const QString& value)
-{
- if (!d->fragmentShaderSource.isEmpty() || value != d->fragmentShader)
- {
- d->fragmentShader = value;
- d->regenerate = true;
- d->fragmentShaderSource = QUrl();
- emit shaderChanged();
- emit effectChanged();
- }
-}
-
-/*!
- \qmlproperty QUrl ShaderProgram::vertexShaderSource
- This property allows the source for the vertex shader to be set to the contents
- of a file containing shader source code. This property and the vertexShader()
- property both effect the same underlying object, so setting one will override
- the other.
-
- Note that at present networked URLs are not supported, only local files. If a
- URL has not been set for the vertex shader, for example because it was
- specified via the vertexShader() in-line shader code property, then this property
- will return a null (empty) QUrl.
-
- \sa vertexShader, fragmentShaderSource
-*/
-QUrl ShaderProgram::vertexShaderSource() const
-{
- return d->vertexShaderSource;
-}
-
-void ShaderProgram::setVertexShaderSource(const QUrl &url)
-{
- if (!url.isEmpty() && url.isValid() && url != d->vertexShaderSource)
- {
- if (url.scheme() == QLatin1String("file"))
- {
- QString fn = url.toLocalFile();
- QFile vs(fn);
- if (vs.open(QIODevice::ReadOnly))
- {
- d->vertexShader = vs.readAll();
- d->vertexShaderSource = url;
- emit shaderChanged();
- emit effectChanged();
- d->regenerate = true;
- }
- else
- {
- qWarning() << "Unable to read" << url;
- }
- }
- else
- {
- qWarning() << "vertexShaderSource property does not (yet) support non-file URLs";
- }
- }
-}
-
-/*!
- \qmlproperty QUrl ShaderProgram::fragmentShaderSource
- This property allows the source for the fragment shader to be set to the contents
- of a file containing shader source code. This property and the vertexShader()
- property both effect the same underlying object, so setting one will override
- the other.
-
- Note that at present networked URLs are not supported, only local files. If a
- URL has not been set for the fragment shader, for example because it was
- specified via the fragmentShader() in-line shader code property, then this property
- will return a null (empty) QUrl.
-
- \sa fragmentShader, vertexShaderSource
-*/
-QUrl ShaderProgram::fragmentShaderSource() const
-{
- return d->fragmentShaderSource;
-}
-
-void ShaderProgram::setFragmentShaderSource(const QUrl &url)
-{
- if (!url.isEmpty() && url.isValid() && url != d->fragmentShaderSource)
- {
- if (url.scheme() == QLatin1String("file"))
- {
- QString fn = url.toLocalFile();
- QFile fs(fn);
- if (fs.open(QIODevice::ReadOnly))
- {
- d->fragmentShader = fs.readAll();
- d->fragmentShaderSource = url;
- emit shaderChanged();
- emit effectChanged();
- d->regenerate = true;
- }
- else
- {
- qWarning() << "Unable to read fragment shader" << url;
- }
- }
- else
- {
- qWarning() << "fragmentShaderSource property does not (yet) support non-file URLs";
- }
- }
-}
-
-/*!
- \internal
- Enables the effect for a given \a painter. If the effect has not been created yet, this function will
- attempt to do so.
-*/
-void ShaderProgram::enableEffect(QGLPainter *painter)
-{
- if (!d->shadersSupported && !d->regenerate) {
- // Use a simple fallback effect.
- QDeclarativeEffect::enableEffect(painter);
- return;
- }
- if (!d->effect) {
- // note that the ShaderProgramEffect can also be created when this
- // effect is applied to a QGLSceneNode if that happens first
- d->effect = new ShaderProgramEffect(this);
- if (!d->effect->create(d->vertexShader, d->fragmentShader)) {
- delete d->effect;
- d->effect = 0;
- QDeclarativeEffect::enableEffect(painter);
- d->regenerate = false;
- d->shadersSupported = false;
- return;
- }
- d->shadersSupported = true;
- } else if (d->regenerate) {
- if (!d->effect->create(d->vertexShader, d->fragmentShader)) {
- delete d->effect;
- d->effect = 0;
- QDeclarativeEffect::enableEffect(painter);
- d->regenerate = false;
- d->shadersSupported = false;
- return;
- }
- d->shadersSupported = true;
- }
- d->regenerate = false;
- painter->setUserEffect(d->effect);
- painter->setColor(color());
- QGLTexture2D *tex = texture2D();
- painter->glActiveTexture(GL_TEXTURE0);
- if (tex)
- tex->bind();
- else
- glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-/*!
- \internal
- Set a scenenode's material and effect properties to enact this effect.
-
- This can happen before glInitialize, so setup is delayed until the effect is
- used or explicitly initialized.
-*/
-void ShaderProgram::applyTo(QGLSceneNode *node)
-{
- if (!d->effect) {
- // This function is often called during setup, before glInitilization,
- // so create the effect now, and then initializion it later.
- d->effect = new ShaderProgramEffect(this);
- d->regenerate = true;
- }
- node->setUserEffect(d->effect);
-}
-
-/*!
- \internal
- Mark all properties as dirty to be re-uploaded in the next update
-*/
-void ShaderProgram::markAllPropertiesDirty()
-{
- d->effect->setPropertiesDirty();
-}
-
-/*!
- \internal
- Mark a \a property as dirty to be re-uploaded in the next update
- */
-void ShaderProgram::markPropertyDirty(int property)
-{
- d->effect->setPropertyDirty(property);
-}
-
-/*!
- \qmlsignal ShaderProgram::onFinishedLoading()
- Emitted when the last remote resource request is resolved, and implies that
- the effect is ready to be displayed.
-*/
-
-/*!
- \internal
- A subclass without the Q_OBJECT macro in order to use the qt_metacall trick to track property changes.
-
- It is also conveniently placed to connect appropriate properties to
- Effect::effectChanged() to trigger timely updates.
- */
-ShaderProgramPropertyListenerEx::ShaderProgramPropertyListenerEx(ShaderProgram *parent, ShaderProgramEffect* effect)
- : ShaderProgramPropertyListener(parent), effect(effect)
-{
- shaderProgramMethodCount = parent->metaObject()->methodCount();
-}
-
-/*!
- \internal
-*/
-ShaderProgramPropertyListenerEx::~ShaderProgramPropertyListenerEx()
-{
-}
-
-/*!
- \internal
- Find calls to the "imaginary" slots, and mark the appropriate property
- as dirty.
-*/
-int ShaderProgramPropertyListenerEx::qt_metacall(QMetaObject::Call c, int id, void **a)
-{
- if (c == QMetaObject::InvokeMetaMethod )
- {
- if (id >= shaderProgramMethodCount) {
- effect->setPropertyDirty(id - shaderProgramMethodCount);
- emit propertyChanged();
- }
- // Consume the metacall
- return -1;
- }
-
- return ShaderProgramPropertyListener::qt_metacall(c, id, a);
-}
-
-QT_END_NAMESPACE