diff options
author | Kevin Ottens <kevin.ottens@kdab.com> | 2017-01-30 16:04:06 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2017-01-31 08:59:47 +0000 |
commit | cfb6bf0c53d9f70f12802cb25a1c14327615b756 (patch) | |
tree | 5a2ff6d278de0c954f2a28d5608f9020a86b0e6e | |
parent | ae1a3bee761c29edffc5fdbe7b77140f1620a04a (diff) |
Uniform color PBR lighting to Qt3DExtras
Second material using PBR. Still uses environment maps and ignores
regular lights but provide a plain color variant of the material.
Change-Id: Ica2045826f6efdc804240709154b6822b89f4417
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
-rw-r--r-- | src/extras/defaults/defaults.pri | 3 | ||||
-rw-r--r-- | src/extras/defaults/qmetalroughmaterial.cpp | 328 | ||||
-rw-r--r-- | src/extras/defaults/qmetalroughmaterial.h | 105 | ||||
-rw-r--r-- | src/extras/defaults/qmetalroughmaterial_p.h | 110 | ||||
-rw-r--r-- | src/extras/extras.qrc | 1 | ||||
-rw-r--r-- | src/extras/shaders/gl3/metalroughuniform.frag | 217 | ||||
-rw-r--r-- | src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp | 2 |
7 files changed, 766 insertions, 0 deletions
diff --git a/src/extras/defaults/defaults.pri b/src/extras/defaults/defaults.pri index 58204bd71..cab26cafd 100644 --- a/src/extras/defaults/defaults.pri +++ b/src/extras/defaults/defaults.pri @@ -30,6 +30,8 @@ HEADERS += \ $$PWD/qorbitcameracontroller_p.h \ $$PWD/qtexturematerial.h \ $$PWD/qtexturematerial_p.h \ + $$PWD/qmetalroughmaterial.h \ + $$PWD/qmetalroughmaterial_p.h \ $$PWD/qtexturedmetalroughmaterial.h \ $$PWD/qtexturedmetalroughmaterial_p.h @@ -50,5 +52,6 @@ SOURCES += \ $$PWD/qfirstpersoncameracontroller.cpp \ $$PWD/qorbitcameracontroller.cpp \ $$PWD/qtexturematerial.cpp \ + $$PWD/qmetalroughmaterial.cpp \ $$PWD/qtexturedmetalroughmaterial.cpp diff --git a/src/extras/defaults/qmetalroughmaterial.cpp b/src/extras/defaults/qmetalroughmaterial.cpp new file mode 100644 index 000000000..e895da639 --- /dev/null +++ b/src/extras/defaults/qmetalroughmaterial.cpp @@ -0,0 +1,328 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmetalroughmaterial.h" +#include "qmetalroughmaterial_p.h" +#include <Qt3DRender/qfilterkey.h> +#include <Qt3DRender/qmaterial.h> +#include <Qt3DRender/qeffect.h> +#include <Qt3DRender/qtexture.h> +#include <Qt3DRender/qtechnique.h> +#include <Qt3DRender/qshaderprogram.h> +#include <Qt3DRender/qparameter.h> +#include <Qt3DRender/qrenderpass.h> +#include <Qt3DRender/qgraphicsapifilter.h> +#include <QUrl> +#include <QVector3D> +#include <QVector4D> + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; + +namespace Qt3DExtras { + +QMetalRoughMaterialPrivate::QMetalRoughMaterialPrivate() + : QMaterialPrivate() + , m_environmentIrradianceTexture(new QTexture2D()) + , m_environmentSpecularTexture(new QTexture2D()) + , m_baseColorParameter(new QParameter(QStringLiteral("baseColor"), QColor("grey"))) + , m_metallicParameter(new QParameter(QStringLiteral("metallic"), 0.0f)) + , m_roughnessParameter(new QParameter(QStringLiteral("roughness"), 0.0f)) + , m_environmentIrradianceParameter(new QParameter(QStringLiteral("skyIrradiance"), m_environmentIrradianceTexture)) + , m_environmentSpecularParameter(new QParameter(QStringLiteral("skySpecular"), m_environmentSpecularTexture)) + , m_exposureParameter(new QParameter(QStringLiteral("exposure"), 0.0f)) + , m_metalRoughEffect(new QEffect()) + , m_metalRoughGL3Technique(new QTechnique()) + , m_metalRoughGL3RenderPass(new QRenderPass()) + , m_metalRoughGL3Shader(new QShaderProgram()) + , m_filterKey(new QFilterKey) +{ + m_environmentIrradianceTexture->setMagnificationFilter(QAbstractTexture::Linear); + m_environmentIrradianceTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear); + m_environmentIrradianceTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat)); + m_environmentIrradianceTexture->setGenerateMipMaps(true); + m_environmentIrradianceTexture->setMaximumAnisotropy(16.0f); + + m_environmentSpecularTexture->setMagnificationFilter(QAbstractTexture::Linear); + m_environmentSpecularTexture->setMinificationFilter(QAbstractTexture::LinearMipMapLinear); + m_environmentSpecularTexture->setWrapMode(QTextureWrapMode(QTextureWrapMode::Repeat)); + m_environmentSpecularTexture->setGenerateMipMaps(true); + m_environmentSpecularTexture->setMaximumAnisotropy(16.0f); +} + +void QMetalRoughMaterialPrivate::init() +{ + connect(m_baseColorParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleBaseColorChanged); + connect(m_metallicParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleMetallicChanged); + connect(m_roughnessParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleRoughnessChanged); + connect(m_environmentIrradianceParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleEnvironmentIrradianceChanged); + connect(m_environmentSpecularParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleEnvironmentSpecularChanged); + connect(m_exposureParameter, &Qt3DRender::QParameter::valueChanged, + this, &QMetalRoughMaterialPrivate::handleExposureChanged); + + m_metalRoughGL3Shader->setVertexShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalrough.vert")))); + m_metalRoughGL3Shader->setFragmentShaderCode(QShaderProgram::loadSource(QUrl(QStringLiteral("qrc:/shaders/gl3/metalroughuniform.frag")))); + + m_metalRoughGL3Technique->graphicsApiFilter()->setApi(QGraphicsApiFilter::OpenGL); + m_metalRoughGL3Technique->graphicsApiFilter()->setMajorVersion(3); + m_metalRoughGL3Technique->graphicsApiFilter()->setMinorVersion(1); + m_metalRoughGL3Technique->graphicsApiFilter()->setProfile(QGraphicsApiFilter::CoreProfile); + + Q_Q(QMetalRoughMaterial); + m_filterKey->setParent(q); + m_filterKey->setName(QStringLiteral("renderingStyle")); + m_filterKey->setValue(QStringLiteral("forward")); + + m_metalRoughGL3Technique->addFilterKey(m_filterKey); + m_metalRoughGL3RenderPass->setShaderProgram(m_metalRoughGL3Shader); + m_metalRoughGL3Technique->addRenderPass(m_metalRoughGL3RenderPass); + m_metalRoughEffect->addTechnique(m_metalRoughGL3Technique); + + m_metalRoughEffect->addParameter(m_baseColorParameter); + m_metalRoughEffect->addParameter(m_metallicParameter); + m_metalRoughEffect->addParameter(m_roughnessParameter); + m_metalRoughEffect->addParameter(m_environmentIrradianceParameter); + m_metalRoughEffect->addParameter(m_environmentSpecularParameter); + m_metalRoughEffect->addParameter(m_exposureParameter); + + q->setEffect(m_metalRoughEffect); +} + +void QMetalRoughMaterialPrivate::handleBaseColorChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->baseColorChanged(var.value<QColor>()); +} + +void QMetalRoughMaterialPrivate::handleMetallicChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->metallicChanged(var.toFloat()); +} +void QMetalRoughMaterialPrivate::handleRoughnessChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->roughnessChanged(var.toFloat()); +} + +void QMetalRoughMaterialPrivate::handleEnvironmentIrradianceChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->environmentIrradianceChanged(var.value<QAbstractTexture *>()); +} + +void QMetalRoughMaterialPrivate::handleEnvironmentSpecularChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->environmentSpecularChanged(var.value<QAbstractTexture *>()); +} + +void QMetalRoughMaterialPrivate::handleExposureChanged(const QVariant &var) +{ + Q_Q(QMetalRoughMaterial); + emit q->exposureChanged(var.toFloat()); +} + +/*! + \class Qt3DExtras::QMetalRoughMaterial + \brief The QMetalRoughMaterial provides a default implementation of PBR + lighting. + \inmodule Qt3DExtras + \since 5.9 + \inherits Qt3DRender::QMaterial + + This material uses an effect with a single render pass approach and performs per fragment + lighting. Techniques are provided for OpenGL 3 only. +*/ + +/*! + Constructs a new QMetalRoughMaterial instance with parent object \a parent. +*/ +QMetalRoughMaterial::QMetalRoughMaterial(QNode *parent) + : QMaterial(*new QMetalRoughMaterialPrivate, parent) +{ + Q_D(QMetalRoughMaterial); + d->init(); +} + +/*! \internal */ +QMetalRoughMaterial::QMetalRoughMaterial(QMetalRoughMaterialPrivate &dd, QNode *parent) + : QMaterial(dd, parent) +{ + Q_D(QMetalRoughMaterial); + d->init(); +} + +/*! + Destroys the QMetalRoughMaterial instance. +*/ +QMetalRoughMaterial::~QMetalRoughMaterial() +{ +} + +/*! + \property QMetalRoughMaterial::baseColor + + Holds the current base color of the material. +*/ +QColor QMetalRoughMaterial::baseColor() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_baseColorParameter->value().value<QColor>(); +} + +/*! + \property QMetalRoughMaterial::metallic + + Holds the current metallic level of the material, since is a value between 0 (purely dielectric, the default) + and 1 (purely metallic). +*/ +float QMetalRoughMaterial::metallic() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_metallicParameter->value().toFloat(); +} + +/*! + \property QMetalRoughMaterial::roughness + + Holds the current roughness level of the material. +*/ +float QMetalRoughMaterial::roughness() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_roughnessParameter->value().toFloat(); +} + +/*! + \property QMetalRoughMaterial::environmentIrradiance + + Holds the current environment irradiance map texture. + + By default, the environment irradiance texture has the following properties: + + \list + \li Linear minification and magnification filters + \li Linear mipmap with mipmapping enabled + \li Repeat wrap mode + \li Maximum anisotropy of 16.0 + \endlist +*/ +QAbstractTexture *QMetalRoughMaterial::environmentIrradiance() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_environmentIrradianceParameter->value().value<QAbstractTexture *>(); +} + +/*! + \property QMetalRoughMaterial::environmentSpecular + + Holds the current environment specular map texture. + + By default, the environment specular texture has the following properties: + + \list + \li Linear minification and magnification filters + \li Linear mipmap with mipmapping enabled + \li Repeat wrap mode + \li Maximum anisotropy of 16.0 + \endlist +*/ +QAbstractTexture *QMetalRoughMaterial::environmentSpecular() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_environmentSpecularParameter->value().value<QAbstractTexture *>(); +} + +/*! + \property QMetalRoughMaterial::exposure + + Holds the current exposure as a float value. +*/ +float QMetalRoughMaterial::exposure() const +{ + Q_D(const QMetalRoughMaterial); + return d->m_exposureParameter->value().toFloat(); +} + +void QMetalRoughMaterial::setBaseColor(const QColor &baseColor) +{ + Q_D(QMetalRoughMaterial); + d->m_baseColorParameter->setValue(QVariant::fromValue(baseColor)); +} + +void QMetalRoughMaterial::setMetallic(float metallic) +{ + Q_D(QMetalRoughMaterial); + d->m_metallicParameter->setValue(QVariant::fromValue(metallic)); +} + +void QMetalRoughMaterial::setRoughness(float roughness) +{ + Q_D(QMetalRoughMaterial); + d->m_roughnessParameter->setValue(QVariant::fromValue(roughness)); +} + +void QMetalRoughMaterial::setEnvironmentIrradiance(QAbstractTexture *environmentIrradiance) +{ + Q_D(QMetalRoughMaterial); + d->m_environmentIrradianceParameter->setValue(QVariant::fromValue(environmentIrradiance)); +} + +void QMetalRoughMaterial::setEnvironmentSpecular(QAbstractTexture *environmentSpecular) +{ + Q_D(QMetalRoughMaterial); + d->m_environmentSpecularParameter->setValue(QVariant::fromValue(environmentSpecular)); +} + +void QMetalRoughMaterial::setExposure(float exposure) +{ + Q_D(QMetalRoughMaterial); + d->m_exposureParameter->setValue(exposure); +} + +} // namespace Qt3DExtras + +QT_END_NAMESPACE diff --git a/src/extras/defaults/qmetalroughmaterial.h b/src/extras/defaults/qmetalroughmaterial.h new file mode 100644 index 000000000..914cef6ca --- /dev/null +++ b/src/extras/defaults/qmetalroughmaterial.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QMETALROUGHMATERIAL_H +#define QT3DEXTRAS_QMETALROUGHMATERIAL_H + +#include <Qt3DExtras/qt3dextras_global.h> +#include <Qt3DRender/qmaterial.h> +#include <QtGui/qcolor.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +class QAbstractTexture; +} + +namespace Qt3DExtras { + +class QMetalRoughMaterialPrivate; + +class QT3DEXTRASSHARED_EXPORT QMetalRoughMaterial : public Qt3DRender::QMaterial +{ + Q_OBJECT + Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged) + Q_PROPERTY(float metallic READ metallic WRITE setMetallic NOTIFY metallicChanged) + Q_PROPERTY(float roughness READ roughness WRITE setRoughness NOTIFY roughnessChanged) + Q_PROPERTY(Qt3DRender::QAbstractTexture *environmentIrradiance READ environmentIrradiance WRITE setEnvironmentIrradiance NOTIFY environmentIrradianceChanged) + Q_PROPERTY(Qt3DRender::QAbstractTexture *environmentSpecular READ environmentSpecular WRITE setEnvironmentSpecular NOTIFY environmentSpecularChanged) + Q_PROPERTY(float exposure READ exposure WRITE setExposure NOTIFY exposureChanged) + +public: + explicit QMetalRoughMaterial(Qt3DCore::QNode *parent = nullptr); + ~QMetalRoughMaterial(); + + QColor baseColor() const; + float metallic() const; + float roughness() const; + Qt3DRender::QAbstractTexture *environmentIrradiance() const; + Qt3DRender::QAbstractTexture *environmentSpecular() const; + float exposure() const; + +public Q_SLOTS: + void setBaseColor(const QColor &baseColor); + void setMetallic(float metallic); + void setRoughness(float roughness); + void setEnvironmentIrradiance(Qt3DRender::QAbstractTexture *environmentIrradiance); + void setEnvironmentSpecular(Qt3DRender::QAbstractTexture *environmentSpecular); + void setExposure(float exposure); + +Q_SIGNALS: + void baseColorChanged(const QColor &baseColor); + void metallicChanged(float metallic); + void roughnessChanged(float roughness); + void environmentIrradianceChanged(Qt3DRender::QAbstractTexture *environmentIrradiance); + void environmentSpecularChanged(Qt3DRender::QAbstractTexture *environmentSpecular); + void exposureChanged(float exposure); + +protected: + QMetalRoughMaterial(QMetalRoughMaterialPrivate &dd, Qt3DCore::QNode *parent = nullptr); + +private: + Q_DECLARE_PRIVATE(QMetalRoughMaterial) +}; + +} // namespace Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QMETALROUGHMATERIAL_H diff --git a/src/extras/defaults/qmetalroughmaterial_p.h b/src/extras/defaults/qmetalroughmaterial_p.h new file mode 100644 index 000000000..d287f0093 --- /dev/null +++ b/src/extras/defaults/qmetalroughmaterial_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT3DEXTRAS_QMETALROUGHMATERIAL_P_H +#define QT3DEXTRAS_QMETALROUGHMATERIAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DRender/private/qmaterial_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class QFilterKey; +class QEffect; +class QAbstractTexture; +class QTechnique; +class QParameter; +class QShaderProgram; +class QRenderPass; + +} // namespace Qt3DRender + +namespace Qt3DExtras { + +class QMetalRoughMaterial; + +class QMetalRoughMaterialPrivate : public Qt3DRender::QMaterialPrivate +{ +public: + QMetalRoughMaterialPrivate(); + + void init(); + + void handleBaseColorChanged(const QVariant &var); + void handleMetallicChanged(const QVariant &var); + void handleRoughnessChanged(const QVariant &var); + void handleEnvironmentIrradianceChanged(const QVariant &var); + void handleEnvironmentSpecularChanged(const QVariant &var); + void handleExposureChanged(const QVariant &var); + + Qt3DRender::QAbstractTexture *m_environmentIrradianceTexture; + Qt3DRender::QAbstractTexture *m_environmentSpecularTexture; + Qt3DRender::QParameter *m_baseColorParameter; + Qt3DRender::QParameter *m_metallicParameter; + Qt3DRender::QParameter *m_roughnessParameter; + Qt3DRender::QParameter *m_environmentIrradianceParameter; + Qt3DRender::QParameter *m_environmentSpecularParameter; + Qt3DRender::QParameter *m_exposureParameter; + Qt3DRender::QEffect *m_metalRoughEffect; + Qt3DRender::QTechnique *m_metalRoughGL3Technique; + Qt3DRender::QRenderPass *m_metalRoughGL3RenderPass; + Qt3DRender::QShaderProgram *m_metalRoughGL3Shader; + Qt3DRender::QFilterKey *m_filterKey; + + Q_DECLARE_PUBLIC(QMetalRoughMaterial) +}; + +} // Qt3DExtras + +QT_END_NAMESPACE + +#endif // QT3DEXTRAS_QMETALROUGHMATERIAL_P_H + diff --git a/src/extras/extras.qrc b/src/extras/extras.qrc index 04437d599..133955e7d 100644 --- a/src/extras/extras.qrc +++ b/src/extras/extras.qrc @@ -41,6 +41,7 @@ <file>shaders/es2/unlittexture.vert</file> <file>shaders/gl3/metalrough.vert</file> <file>shaders/gl3/metalrough.frag</file> + <file>shaders/gl3/metalroughuniform.frag</file> <file>shaders/gl3/distancefieldtext.vert</file> <file>shaders/gl3/distancefieldtext.frag</file> <file>shaders/es2/distancefieldtext.frag</file> diff --git a/src/extras/shaders/gl3/metalroughuniform.frag b/src/extras/shaders/gl3/metalroughuniform.frag new file mode 100644 index 000000000..dfc174e8b --- /dev/null +++ b/src/extras/shaders/gl3/metalroughuniform.frag @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#version 150 + +in vec2 texCoord; +in vec3 worldPosition; +in vec3 worldNormal; +in vec4 worldTangent; + +out vec4 fragColor; + +// Qt 3D built in uniforms +uniform vec3 eyePosition; // World space eye position +uniform float time; // Time in seconds + +// Pre-convolved environment maps +uniform samplerCube skyIrradiance; // For diffuse contribution +uniform samplerCube skySpecular; // For specular contribution + +// PBR Material maps +uniform vec4 baseColor; +uniform float metallic; +uniform float roughness; + +// Roughness -> mip level mapping +uniform float maxT = 0.939824; +uniform float mipLevels = 11.0; +uniform float mipOffset = 5.0; + +// Exposure correction +uniform float exposure = 0.0; + +mat3 calcWorldSpaceToTangentSpaceMatrix(const in vec3 wNormal, const in vec4 wTangent) +{ + // Make the tangent truly orthogonal to the normal by using Gram-Schmidt. + // This allows to build the tangentMatrix below by simply transposing the + // tangent -> eyespace matrix (which would now be orthogonal) + vec3 wFixedTangent = normalize(wTangent.xyz - dot(wTangent.xyz, wNormal) * wNormal); + + // Calculate binormal vector. No "real" need to renormalize it, + // as built by crossing two normal vectors. + // To orient the binormal correctly, use the fourth coordinate of the tangent, + // which is +1 for a right hand system, and -1 for a left hand system. + vec3 wBinormal = cross(wNormal, wFixedTangent.xyz) * wTangent.w; + + // Construct matrix to transform from world space to tangent space + // This is the transpose of the tangentToWorld transformation matrix + mat3 tangentToWorldMatrix = mat3(wFixedTangent, wBinormal, wNormal); + mat3 worldToTangentMatrix = transpose(tangentToWorldMatrix); + return worldToTangentMatrix; +} + +float roughnessToMipLevel(float roughness) +{ + // HACK: Improve the roughness -> mip level mapping for roughness map from substace painter + // TODO: Use mathematica or similar to improve this mapping more generally + roughness = 0.75 + (1.7 * (roughness - 0.5)); + return (mipLevels - 1.0 - mipOffset) * (1.0 - (1.0 - roughness) / maxT); +} + +vec3 fresnelFactor(const in vec3 color, const in float cosineFactor) +{ + // Calculate the Fresnel effect value + vec3 f = color; + vec3 F = f + (1.0 - f) * pow(1.0 - cosineFactor, 5.0); + return clamp(F, f, vec3(1.0)); +} + +float geometricModel(const in float lDotN, + const in float vDotN, + const in vec3 h) +{ + // Implicit geometric model (equal to denominator in specular model). + // This currently assumes that there is no attenuation by geometric shadowing or + // masking according to the microfacet theory. + return 1.0; +} + +vec3 specularModel(const in vec3 F0, + const in float lDotH, + const in float lDotN, + const in float vDotN, + const in vec3 n, + const in vec3 h) +{ + // Clamp lDotN and vDotN to small positive value to prevent the + // denominator in the reflection equation going to infinity. Balance this + // by using the clamped values in the geometric factor function to + // avoid ugly seams in the specular lighting. + float sDotNPrime = max(lDotN, 0.001); + float vDotNPrime = max(vDotN, 0.001); + + vec3 F = fresnelFactor(F0, lDotH); + float G = geometricModel(sDotNPrime, vDotNPrime, h); + + // TODO: Verify which parts of the BRDF Lys is preconvolving and multiply + // by the remaining factors here. + vec3 cSpec = F * G / (4.0 * sDotNPrime * vDotNPrime); + return clamp(cSpec, vec3(0.0), vec3(1.0)); +} + +vec3 pbrIblModel(const in vec3 wNormal, + const in vec3 wView, + const in vec3 baseColor, + const in float metallic, + const in float roughness) +{ + // Calculate reflection direction of view vector about surface normal + // vector in world space. This is used in the fragment shader to sample + // from the environment textures for a light source. This is equivalent + // to the l vector for punctual light sources. Armed with this, calculate + // the usual factors needed + vec3 n = wNormal; + vec3 l = reflect(-wView, n); + vec3 v = wView; + vec3 h = normalize(l + v); + float vDotN = dot(v, n); + float lDotN = dot(l, n); + float lDotH = dot(l, h); + + // Calculate diffuse component + vec3 diffuseColor = (1.0 - metallic) * baseColor; + vec3 diffuse = diffuseColor * texture(skyIrradiance, l).rgb; + + // Calculate specular component + vec3 dielectricColor = vec3(0.04); + vec3 F0 = mix(dielectricColor, baseColor, metallic); + vec3 specularFactor = specularModel(F0, lDotH, lDotN, vDotN, n, h); + + float lod = roughnessToMipLevel(roughness); + vec3 specularSkyColor = textureLod(skySpecular, l, lod).rgb; + vec3 specular = specularSkyColor * specularFactor; + + // Blend between diffuse and specular to conserve energy + vec3 iblColor = specular + diffuse * (vec3(1.0) - specularFactor); + + // Apply exposure correction + iblColor *= pow(2.0, exposure); + + return iblColor; +} + +vec3 toneMap(const in vec3 c) +{ + return c / (c + vec3(1.0)); +} + +vec3 gammaCorrect(const in vec3 color) +{ + const float gamma = 1.0 / 2.2; + return pow(color, vec3(gamma)); +} + +void main() +{ + vec3 worldView = normalize(eyePosition - worldPosition); + vec3 cLinear = pbrIblModel(worldNormal, + worldView, + baseColor.rgb, + metallic, + roughness); + + // Apply simple (Reinhard) tonemap transform to get into LDR range [0, 1] + vec3 cToneMapped = toneMap(cLinear); + + // Apply gamma correction prior to display + vec3 cGamma = gammaCorrect(cToneMapped); + fragColor = vec4(cGamma, 1.0); +} diff --git a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp index ffa6be945..1edde1e19 100644 --- a/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp +++ b/src/quick3d/imports/extras/qt3dquick3dextrasplugin.cpp @@ -46,6 +46,7 @@ #include <Qt3DExtras/qfirstpersoncameracontroller.h> #include <Qt3DExtras/qforwardrenderer.h> #include <Qt3DExtras/qgoochmaterial.h> +#include <Qt3DExtras/qmetalroughmaterial.h> #include <Qt3DExtras/qnormaldiffusemapalphamaterial.h> #include <Qt3DExtras/qnormaldiffusemapmaterial.h> #include <Qt3DExtras/qnormaldiffusespecularmapmaterial.h> @@ -99,6 +100,7 @@ void Qt3DQuick3DExtrasPlugin::registerTypes(const char *uri) qmlRegisterType<Qt3DExtras::QPerVertexColorMaterial>(uri, 2, 0, "PerVertexColorMaterial"); qmlRegisterType<Qt3DExtras::QGoochMaterial>(uri, 2, 0, "GoochMaterial"); qmlRegisterType<Qt3DExtras::QTextureMaterial>(uri, 2, 0, "TextureMaterial"); + qmlRegisterType<Qt3DExtras::QMetalRoughMaterial>(uri, 2, 2, "MetalRoughMaterial"); qmlRegisterType<Qt3DExtras::QTexturedMetalRoughMaterial>(uri, 2, 2, "TexturedMetalRoughMaterial"); // Meshes |