blob: fe16a7ef936c050d677de136f05569daf73c4aea [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Quick 3D.
**
** $QT_BEGIN_LICENSE:GPL$
** 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 General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) 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.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-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSSGCUSTOMMATERIAL_H
#define QSSGCUSTOMMATERIAL_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtQuick3D/private/qquick3dmaterial_p.h>
#include <QtCore/qvector.h>
#include <QtQuick3DRender/private/qssgrenderbasetypes_p.h>
#include <QtQuick3DRuntimeRender/private/qssgrenderdynamicobjectsystemcommands_p.h>
QT_BEGIN_NAMESPACE
class QQuick3DCustomMaterialShader;
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialTextureInput : public QObject
{
Q_OBJECT
Q_PROPERTY(QQuick3DTexture *texture READ texture WRITE setTexture)
Q_PROPERTY(bool enabled MEMBER enabled)
public:
QQuick3DCustomMaterialTextureInput() = default;
virtual ~QQuick3DCustomMaterialTextureInput() = default;
QQuick3DTexture *m_texture = nullptr;
bool enabled = true;
QQuick3DTexture *texture() const
{
return m_texture;
}
public Q_SLOTS:
void setTexture(QQuick3DTexture *texture)
{
if (m_texture == texture)
return;
QObject *p = parent();
while (p != nullptr) {
if (QQuick3DMaterial *mat = qobject_cast<QQuick3DMaterial *>(p)) {
mat->setDynamicTextureMap(texture);
break;
}
}
m_texture = texture;
Q_EMIT textureDirty(this);
}
Q_SIGNALS:
void textureDirty(QQuick3DCustomMaterialTextureInput *texture);
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialBuffer : public QObject
{
Q_OBJECT
Q_PROPERTY(TextureFormat format READ format WRITE setFormat)
Q_PROPERTY(TextureFilterOperation textureFilterOperation READ textureFilterOperation WRITE setTextureFilterOperation)
Q_PROPERTY(TextureCoordOperation textureCoordOperation READ textureCoordOperation WRITE setTextureCoordOperation)
Q_PROPERTY(float sizeMultiplier MEMBER sizeMultiplier)
Q_PROPERTY(AllocateBufferFlagValues bufferFlags READ bufferFlags WRITE setBufferFlags)
Q_PROPERTY(QByteArray name MEMBER name)
public:
QQuick3DCustomMaterialBuffer() = default;
~QQuick3DCustomMaterialBuffer() override = default;
enum class TextureFilterOperation
{
Unknown = 0,
Nearest,
Linear
};
Q_ENUM(TextureFilterOperation)
enum class TextureCoordOperation
{
Unknown = 0,
ClampToEdge,
MirroredRepeat,
Repeat
};
Q_ENUM(TextureCoordOperation)
enum class AllocateBufferFlagValues
{
None = 0,
SceneLifetime = 1,
};
Q_ENUM(AllocateBufferFlagValues)
enum class TextureFormat {
Unknown = 0,
R8,
R16,
R16F,
R32I,
R32UI,
R32F,
RG8,
RGBA8,
RGB8,
SRGB8,
SRGB8A8,
RGB565,
RGBA16F,
RG16F,
RG32F,
RGB32F,
RGBA32F,
R11G11B10,
RGB9E5,
Depth16,
Depth24,
Depth32,
Depth24Stencil8
};
Q_ENUM(TextureFormat)
dynamic::QSSGAllocateBuffer command {};
TextureFilterOperation textureFilterOperation() const { return TextureFilterOperation(command.m_filterOp); }
void setTextureFilterOperation(TextureFilterOperation op) { command.m_filterOp = QSSGRenderTextureMagnifyingOp(op); }
TextureCoordOperation textureCoordOperation() const { return TextureCoordOperation(command.m_texCoordOp); }
void setTextureCoordOperation(TextureCoordOperation texCoordOp) { command.m_texCoordOp = QSSGRenderTextureCoordOp(texCoordOp); }
float &sizeMultiplier = command.m_sizeMultiplier;
dynamic::QSSGCommand *getCommand() { return &command; }
TextureFormat format() const;
void setFormat(TextureFormat format);
AllocateBufferFlagValues bufferFlags() const { return AllocateBufferFlagValues(int(command.m_bufferFlags)); }
void setBufferFlags(AllocateBufferFlagValues flag) { command.m_bufferFlags = quint32(flag);}
QByteArray &name = command.m_name;
static TextureFormat mapRenderTextureFormat(QSSGRenderTextureFormat::Format fmt);
static QSSGRenderTextureFormat::Format mapTextureFormat(TextureFormat fmt);
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialRenderCommand : public QObject
{
Q_OBJECT
public:
QQuick3DCustomMaterialRenderCommand() = default;
~QQuick3DCustomMaterialRenderCommand() override = default;
virtual dynamic::QSSGCommand *getCommand() { Q_ASSERT(0); return nullptr; }
virtual int bufferCount() const { return 0; }
virtual QQuick3DCustomMaterialBuffer *bufferAt(int idx) const { Q_UNUSED(idx) return nullptr; }
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialBufferInput : public QQuick3DCustomMaterialRenderCommand
{
Q_OBJECT
Q_PROPERTY(QQuick3DCustomMaterialBuffer *buffer READ buffer WRITE setBuffer)
Q_PROPERTY(QByteArray param MEMBER param)
public:
QQuick3DCustomMaterialBufferInput() = default;
~QQuick3DCustomMaterialBufferInput() override = default;
dynamic::QSSGApplyBufferValue command { QByteArray(), QByteArray() };
QByteArray &param = command.m_paramName;
dynamic::QSSGCommand *getCommand() override { return &command; }
int bufferCount() const override { return (m_buffer != nullptr) ? 1 : 0; }
QQuick3DCustomMaterialBuffer *bufferAt(int idx) const override
{
Q_ASSERT(idx < 1 && idx >= 0);
return (m_buffer && idx == 0) ? m_buffer : nullptr;
}
QQuick3DCustomMaterialBuffer *buffer() const { return m_buffer; }
void setBuffer(QQuick3DCustomMaterialBuffer *buffer) {
if (m_buffer == buffer)
return;
if (buffer) {
Q_ASSERT(!buffer->name.isEmpty());
command.m_bufferName = buffer->name;
}
m_buffer = buffer;
}
QQuick3DCustomMaterialBuffer *m_buffer = nullptr;
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialBufferBlit : public QQuick3DCustomMaterialRenderCommand
{
Q_OBJECT
Q_PROPERTY(QQuick3DCustomMaterialBuffer *source READ source WRITE setSource)
Q_PROPERTY(QQuick3DCustomMaterialBuffer *destination READ destination WRITE setDestination)
public:
QQuick3DCustomMaterialBufferBlit() = default;
~QQuick3DCustomMaterialBufferBlit() override = default;
dynamic::QSSGApplyBlitFramebuffer command { QByteArray(), QByteArray() };
dynamic::QSSGCommand *getCommand() override { return &command; }
int bufferCount() const override {
if (m_source != nullptr && m_destination != nullptr)
return 2;
if (m_source || m_destination)
return 1;
return 0;
}
QQuick3DCustomMaterialBuffer *bufferAt(int idx) const override
{
Q_ASSERT(idx < 2 && idx >= 0);
if (idx == 0)
return m_source ? m_source : m_destination;
if (idx == 1 && m_destination)
return m_destination;
return nullptr;
}
QQuick3DCustomMaterialBuffer *source() const { return m_source; }
void setSource(QQuick3DCustomMaterialBuffer *src)
{
if (src == m_source)
return;
if (src) {
Q_ASSERT(!src->name.isEmpty());
command.m_sourceBufferName = src->name;
}
m_source = src;
}
QQuick3DCustomMaterialBuffer *destination() const { return m_destination; }
void setDestination(QQuick3DCustomMaterialBuffer *dest)
{
if (dest == m_destination)
return;
if (dest) {
Q_ASSERT(!dest->name.isEmpty());
command.m_destBufferName = dest->name;
}
m_destination = dest;
}
QQuick3DCustomMaterialBuffer *m_source = nullptr;
QQuick3DCustomMaterialBuffer *m_destination = nullptr;
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialBlending : public QQuick3DCustomMaterialRenderCommand
{
Q_OBJECT
Q_PROPERTY(SrcBlending srcBlending READ srcBlending WRITE setSrcBlending)
Q_PROPERTY(DestBlending destBlending READ destBlending WRITE setDestBlending)
public:
enum class SrcBlending
{
Unknown = 0,
Zero,
One,
SrcColor,
OneMinusSrcColor,
DstColor,
OneMinusDstColor,
SrcAlpha,
OneMinusSrcAlpha,
DstAlpha,
OneMinusDstAlpha,
ConstantColor,
OneMinusConstantColor,
ConstantAlpha,
OneMinusConstantAlpha,
SrcAlphaSaturate
};
Q_ENUM(SrcBlending)
enum class DestBlending
{
Unknown = 0,
Zero,
One,
SrcColor,
OneMinusSrcColor,
DstColor,
OneMinusDstColor,
SrcAlpha,
OneMinusSrcAlpha,
DstAlpha,
OneMinusDstAlpha,
ConstantColor,
OneMinusConstantColor,
ConstantAlpha,
OneMinusConstantAlpha
};
Q_ENUM(DestBlending)
QQuick3DCustomMaterialBlending() = default;
~QQuick3DCustomMaterialBlending() override = default;
dynamic::QSSGApplyBlending command { QSSGRenderSrcBlendFunc::Unknown, QSSGRenderDstBlendFunc::Unknown };
DestBlending destBlending() const
{
return DestBlending(command.m_dstBlendFunc);
}
SrcBlending srcBlending() const
{
return SrcBlending(command.m_srcBlendFunc);
}
dynamic::QSSGCommand *getCommand() override { return &command; }
public Q_SLOTS:
void setDestBlending(DestBlending destBlending)
{
command.m_dstBlendFunc = QSSGRenderDstBlendFunc(destBlending);
}
void setSrcBlending(SrcBlending srcBlending)
{
command.m_srcBlendFunc= QSSGRenderSrcBlendFunc(srcBlending);
}
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialRenderState : public QQuick3DCustomMaterialRenderCommand
{
Q_OBJECT
Q_PROPERTY(RenderState renderState READ renderState WRITE setRenderState)
Q_PROPERTY(bool enabled MEMBER enabled)
public:
enum class RenderState
{
Unknown = 0,
Blend,
DepthTest = 3,
StencilTest,
ScissorTest,
DepthWrite,
Multisample
};
Q_ENUM(RenderState)
QQuick3DCustomMaterialRenderState() = default;
~QQuick3DCustomMaterialRenderState() override = default;
dynamic::QSSGApplyRenderState command { QSSGRenderState::Unknown, false };
bool &enabled = command.m_enabled;
RenderState renderState() const
{
return RenderState(command.m_renderState);
}
dynamic::QSSGCommand *getCommand() override { return &command; }
public Q_SLOTS:
void setRenderState(RenderState renderState)
{
command.m_renderState = QSSGRenderState(renderState);
}
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialRenderPass : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QQuick3DCustomMaterialRenderCommand> commands READ commands)
Q_PROPERTY(QQuick3DCustomMaterialBuffer *output MEMBER outputBuffer)
Q_PROPERTY(QQmlListProperty<QQuick3DCustomMaterialShader> shaders READ shaders)
public:
QQuick3DCustomMaterialRenderPass() = default;
~QQuick3DCustomMaterialRenderPass() override = default;
static void qmlAppendCommand(QQmlListProperty<QQuick3DCustomMaterialRenderCommand> *list, QQuick3DCustomMaterialRenderCommand *command);
static QQuick3DCustomMaterialRenderCommand *qmlCommandAt(QQmlListProperty<QQuick3DCustomMaterialRenderCommand> *list, int index);
static int qmlCommandCount(QQmlListProperty<QQuick3DCustomMaterialRenderCommand> *list);
static void qmlAppendShader(QQmlListProperty<QQuick3DCustomMaterialShader> *list, QQuick3DCustomMaterialShader *shader);
static QQuick3DCustomMaterialShader *qmlShaderAt(QQmlListProperty<QQuick3DCustomMaterialShader> *list, int index);
static int qmlShaderCount(QQmlListProperty<QQuick3DCustomMaterialShader> *list);
static void qmlShaderClear(QQmlListProperty<QQuick3DCustomMaterialShader> *list);
QQmlListProperty<QQuick3DCustomMaterialRenderCommand> commands();
QVector<QQuick3DCustomMaterialRenderCommand *> m_commands;
QQuick3DCustomMaterialBuffer *outputBuffer = nullptr;
QQmlListProperty<QQuick3DCustomMaterialShader> shaders();
QVarLengthArray<QQuick3DCustomMaterialShader *, 5> m_shaders { nullptr, nullptr, nullptr, nullptr, nullptr };
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialShaderInfo : public QObject
{
Q_OBJECT
Q_PROPERTY(QByteArray version MEMBER version)
Q_PROPERTY(QByteArray type MEMBER type)
Q_PROPERTY(qint32 shaderKey MEMBER shaderKey)
public:
QQuick3DCustomMaterialShaderInfo() = default;
~QQuick3DCustomMaterialShaderInfo() override = default;
QByteArray version;
QByteArray type; // I.e., GLSL
QByteArray shaderPrefix = QByteArrayLiteral("#include \"customMaterial.glsllib\"\n");
enum class MaterialShaderKeyValues
{
Diffuse = 1 << 0,
Specular = 1 << 1,
Cutout = 1 << 2,
Refraction = 1 << 3,
Transparent = 1 << 4,
Displace = 1 << 5,
Transmissive = 1 << 6,
Glossy = Diffuse | Specular,
};
Q_ENUM(MaterialShaderKeyValues)
Q_DECLARE_FLAGS(MaterialShaderKeyFlags, MaterialShaderKeyValues)
qint32 shaderKey {0};
bool isValid() const { return !(version.isEmpty() && type.isEmpty() && shaderPrefix.isEmpty()); }
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterialShader : public QObject
{
Q_OBJECT
Q_PROPERTY(QByteArray shader MEMBER shader)
Q_PROPERTY(Stage stage MEMBER stage)
public:
QQuick3DCustomMaterialShader() = default;
virtual ~QQuick3DCustomMaterialShader() = default;
enum class Stage : quint8
{
Shared,
Vertex,
Fragment,
Geometry,
Compute
};
Q_ENUM(Stage)
QByteArray shader;
Stage stage;
};
class Q_QUICK3D_EXPORT QQuick3DCustomMaterial : public QQuick3DMaterial
{
Q_OBJECT
Q_PROPERTY(bool hasTransparency READ hasTransparency WRITE setHasTransparency NOTIFY hasTransparencyChanged)
Q_PROPERTY(bool hasRefraction READ hasRefraction WRITE setHasRefraction NOTIFY hasRefractionChanged)
Q_PROPERTY(bool alwaysDirty READ alwaysDirty WRITE setAlwaysDirty NOTIFY alwaysDirtyChanged)
Q_PROPERTY(QQuick3DCustomMaterialShaderInfo *shaderInfo READ shaderInfo WRITE setShaderInfo)
Q_PROPERTY(QQmlListProperty<QQuick3DCustomMaterialRenderPass> passes READ passes)
public:
QQuick3DCustomMaterial();
~QQuick3DCustomMaterial() override;
QQuick3DObject::Type type() const override;
bool hasTransparency() const;
bool hasRefraction() const;
bool alwaysDirty() const;
QQuick3DCustomMaterialShaderInfo *shaderInfo() const;
QQmlListProperty<QQuick3DCustomMaterialRenderPass> passes();
public Q_SLOTS:
void setHasTransparency(bool hasTransparency);
void setHasRefraction(bool hasRefraction);
void setShaderInfo(QQuick3DCustomMaterialShaderInfo *shaderInfo);
void setAlwaysDirty(bool alwaysDirty);
Q_SIGNALS:
void hasTransparencyChanged(bool hasTransparency);
void hasRefractionChanged(bool hasRefraction);
void alwaysDirtyChanged(bool alwaysDirty);
protected:
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
void markAllDirty() override;
private Q_SLOTS:
void onPropertyDirty();
void onTextureDirty(QQuick3DCustomMaterialTextureInput *texture);
private:
enum Dirty {
TextureDirty = 0x1,
PropertyDirty = 0x2
};
// Passes
static void qmlAppendPass(QQmlListProperty<QQuick3DCustomMaterialRenderPass> *list, QQuick3DCustomMaterialRenderPass *pass);
static QQuick3DCustomMaterialRenderPass *qmlPassAt(QQmlListProperty<QQuick3DCustomMaterialRenderPass> *list, int index);
static int qmlPassCount(QQmlListProperty<QQuick3DCustomMaterialRenderPass> *list);
void markDirty(QQuick3DCustomMaterial::Dirty type)
{
if (!(m_dirtyAttributes & quint32(type))) {
m_dirtyAttributes |= quint32(type);
update();
}
}
quint32 m_dirtyAttributes = 0xffffffff;
bool m_hasTransparency = false;
bool m_hasRefraction = false;
QQuick3DCustomMaterialShaderInfo *m_shaderInfo = nullptr;
QVector<QQuick3DCustomMaterialRenderPass *> m_passes;
bool m_alwaysDirty = false;
};
QT_END_NAMESPACE
#endif // QSSGCUSTOMMATERIAL_H