diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-11-01 10:59:33 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2019-11-01 11:02:41 +0200 |
commit | 92e34b4a3f0448026da7934938e67aa8f759e601 (patch) | |
tree | 246ca82bb56692b74e48d2ed6d1f86dc59d55f93 | |
parent | 63a5c17ba13eebc4fd91ba785a48dc783c437c01 (diff) | |
parent | 25236c672d81a73ee8754dbd764eb8a2a26d866e (diff) |
Merge remote-tracking branch 'origin/2.5'
Change-Id: Ia7d71a74df92909071c0806b70b783dba6feb1fe
85 files changed, 1150 insertions, 156 deletions
diff --git a/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gauge_round_background.dae b/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gauge_round_background.dae index c7b0753..4af14bc 100644 --- a/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gauge_round_background.dae +++ b/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gauge_round_background.dae @@ -91,7 +91,7 @@ </library_effects> <library_images> <image id="file1" name="file1"> - <init_from>../../../../../Documents/maya/projects/StudioModelLibrary/gradient.png</init_from> + <init_from>gradient.png</init_from> <extra> <technique profile="OpenCOLLADAMaya"> <originalMayaNodeId sid="originalMayaNodeId" type="string">file1</originalMayaNodeId> @@ -224,4 +224,4 @@ <source_data_base_uri>file:///C:/Users/tetammin/Documents/maya/projects/default/</source_data_base_uri> </technique> </extra> -</COLLADA>
\ No newline at end of file +</COLLADA> diff --git a/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gradient.png b/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gradient.png Binary files differnew file mode 100644 index 0000000..70b9fb8 --- /dev/null +++ b/Studio/Content/Models Library/Automotive/Cluster/Backgrounds/gradient.png diff --git a/examples/studio3d/dynamicloading/StartupProgress.qml b/examples/studio3d/dynamicloading/StartupProgress.qml new file mode 100644 index 0000000..c845588 --- /dev/null +++ b/examples/studio3d/dynamicloading/StartupProgress.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $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$ +** +****************************************************************************/ + +import QtQuick.Controls 2.5 +import QtQuick 2.12 + +Rectangle { + width: 180 + height: 60 + radius: 16 + anchors.centerIn: parent + color: "white" + antialiasing: true + property alias progressEnabled: progressBar.enabled + property alias textColor: text.color + Text { + id: text + anchors.centerIn: parent + text: "Loading presentation..." + color: "black" + + } + ProgressBar { + id: progressBar + anchors.left: text.left + anchors.top: text.bottom + width: text.width + indeterminate: true + } +} diff --git a/examples/studio3d/dynamicloading/doc/src/dynamicloading.qdoc b/examples/studio3d/dynamicloading/doc/src/dynamicloading.qdoc new file mode 100644 index 0000000..20af763 --- /dev/null +++ b/examples/studio3d/dynamicloading/doc/src/dynamicloading.qdoc @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example dynamicloading + \title Qt 3D Studio Runtime: Dynamic Loading Example + \ingroup OpenGLRuntime-examples-qml + \brief Demonstrates how resources can be loaded dynamically. + + \e {This example demonstrates deferred loading.} + + \include examples-run.qdocinc + + \section1 Description + + The presentation consists of three slides with images, effect, subpresentation and + custom material. Images and subpresentation are loaded dynamically before entering + the slide using the \l{Presentation::preloadSlide}{preloadSlide} function and unloaded + when exiting a slide using the \l{Presentation::unloadSlide}{unloadSlide} function. + + \snippet dynamicloading/main.qml 1 +*/ diff --git a/examples/studio3d/dynamicloading/dynamicloading.pro b/examples/studio3d/dynamicloading/dynamicloading.pro new file mode 100644 index 0000000..af8ed76 --- /dev/null +++ b/examples/studio3d/dynamicloading/dynamicloading.pro @@ -0,0 +1,26 @@ +TEMPLATE = app + +QT += quick widgets qml studio3d +CONFIG += c++11 + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Refer to the documentation for the +# deprecated API to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/studio3d/$$TARGET +INSTALLS += target + +OTHER_FILES += \ + doc/src/dynamicloading.qdoc diff --git a/examples/studio3d/dynamicloading/main.cpp b/examples/studio3d/dynamicloading/main.cpp new file mode 100644 index 0000000..4894be7 --- /dev/null +++ b/examples/studio3d/dynamicloading/main.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $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$ +** +****************************************************************************/ + +#include <QtWidgets/QApplication> +#include <QtQuick/QQuickView> +#include <qstudio3dglobal.h> + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + QSurfaceFormat::setDefaultFormat(Q3DS::surfaceFormat()); + + QQuickView viewer; + viewer.setSource(QUrl("qrc:/main.qml")); + viewer.setTitle(QStringLiteral("Qt 3D Studio Example")); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); + viewer.resize(1680, 1050); + viewer.show(); + return app.exec(); +} diff --git a/examples/studio3d/dynamicloading/main.qml b/examples/studio3d/dynamicloading/main.qml new file mode 100644 index 0000000..be2ab9b --- /dev/null +++ b/examples/studio3d/dynamicloading/main.qml @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $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$ +** +****************************************************************************/ + +import QtQuick 2.12 +import QtStudio3D.OpenGL 2.5 + +Item { + id: mainview + anchors.fill: parent + visible: true + + StartupProgress { + id: progress + } + Studio3D { + id: studio3D + anchors.fill: parent + asyncInit: true + + ViewerSettings { + showRenderStats: false + scaleMode: ViewerSettings.ScaleModeCenter + } + //![1] + Presentation { + property string slidePath: "dynamicloading:Scene:Slide" + property int curSlideIndex: 1 + property int maxSlideIndex: 3 + + id: presentation + delayedLoading: true + source: "qrc:/presentation/dynamicloading.uia" + + onSlideEntered: { + console.log("Entered: " + name) + + curSlideIndex = index + 1 + if (curSlideIndex > maxSlideIndex) + curSlideIndex = 1 + console.log("preloadSlide: " + slidePath + curSlideIndex) + preloadSlide(slidePath + curSlideIndex) + } + + onSlideExited: { + console.log("Exited: " + name) + unloadSlide(name) + } + } + //![1] + onPresentationReady: progress.visible = false + } +} diff --git a/examples/studio3d/dynamicloading/presentation/dynamicloading.uia b/examples/studio3d/dynamicloading/presentation/dynamicloading.uia new file mode 100644 index 0000000..733f47d --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/dynamicloading.uia @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<application xmlns="http://qt.io/qt3dstudio/uia"> + <assets initial="dynamicloading"> + <presentation id="dynamicloading" src="presentations/dynamicloading.uip"/> + <presentation id="subpres" src="presentations/subpres.uip"/> + </assets> +</application> diff --git a/examples/studio3d/dynamicloading/presentation/effects/FullScreenTextureOverlay.effect b/examples/studio3d/dynamicloading/presentation/effects/FullScreenTextureOverlay.effect new file mode 100644 index 0000000..8cfde54 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/effects/FullScreenTextureOverlay.effect @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<Effect> + <MetaData> + <Property name="Overlay" formalName="Overlay Texture" description="Overlay texture" type="Texture" clamp="repeat" /> + <Property name="overlay_repeat" formalName="Repeat" min="0" max="50" default="1" description="Times to repeat the image over screen."/> + <Property name="alpha" formalName="Alpha" min="0" max="1" default="0.5" description="Overlay blend factor"/> + </MetaData> + <Shaders> + <Shared></Shared> + <FragmentShaderShared></FragmentShaderShared> + <Shader name="main"> + <VertexShader></VertexShader> + <FragmentShader><![CDATA[ +void frag() +{ + vec4 origColor = texture2D_0(TexCoord); + vec4 smp = texture(Overlay, TexCoord.xy * overlay_repeat); + gl_FragColor = alpha * smp + origColor; +} + ]]></FragmentShader> + </Shader> + </Shaders> + <Passes> + <Pass shader="main" input="[source]" output="[dest]"/> + </Passes> +</Effect> + + diff --git a/examples/studio3d/dynamicloading/presentation/fonts/TitilliumWeb-Regular.ttf b/examples/studio3d/dynamicloading/presentation/fonts/TitilliumWeb-Regular.ttf Binary files differnew file mode 100644 index 0000000..6da8219 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/fonts/TitilliumWeb-Regular.ttf diff --git a/examples/studio3d/dynamicloading/presentation/maps/Abstract_001_COLOR.jpg b/examples/studio3d/dynamicloading/presentation/maps/Abstract_001_COLOR.jpg Binary files differnew file mode 100644 index 0000000..97c5df3 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Abstract_001_COLOR.jpg diff --git a/examples/studio3d/dynamicloading/presentation/maps/Blue_Marble_002_COLOR.jpg b/examples/studio3d/dynamicloading/presentation/maps/Blue_Marble_002_COLOR.jpg Binary files differnew file mode 100644 index 0000000..1fab91a --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Blue_Marble_002_COLOR.jpg diff --git a/examples/studio3d/dynamicloading/presentation/maps/Ice_002_COLOR.jpg b/examples/studio3d/dynamicloading/presentation/maps/Ice_002_COLOR.jpg Binary files differnew file mode 100644 index 0000000..0e69b27 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Ice_002_COLOR.jpg diff --git a/examples/studio3d/dynamicloading/presentation/maps/Metal_Streaks.png b/examples/studio3d/dynamicloading/presentation/maps/Metal_Streaks.png Binary files differnew file mode 100644 index 0000000..f2a6d49 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Metal_Streaks.png diff --git a/examples/studio3d/dynamicloading/presentation/maps/Moon_001_COLOR.jpg b/examples/studio3d/dynamicloading/presentation/maps/Moon_001_COLOR.jpg Binary files differnew file mode 100644 index 0000000..3fd374c --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Moon_001_COLOR.jpg diff --git a/examples/studio3d/dynamicloading/presentation/maps/Rock_023_COLOR2.jpg b/examples/studio3d/dynamicloading/presentation/maps/Rock_023_COLOR2.jpg Binary files differnew file mode 100644 index 0000000..39214f9 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/Rock_023_COLOR2.jpg diff --git a/examples/studio3d/dynamicloading/presentation/maps/license.txt b/examples/studio3d/dynamicloading/presentation/maps/license.txt new file mode 100644 index 0000000..62a06f7 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/maps/license.txt @@ -0,0 +1,2 @@ +https://3dtextures.me/ distributed under the terms of +https://creativecommons.org/publicdomain/zero/1.0/ diff --git a/examples/studio3d/dynamicloading/presentation/materials/simplecustom.material b/examples/studio3d/dynamicloading/presentation/materials/simplecustom.material new file mode 100644 index 0000000..51878d2 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/materials/simplecustom.material @@ -0,0 +1,39 @@ +<Material name="simplecustom" version="1.0"> + <MetaData > + <Property formalName="Red" name="red_weight" type="Float" default="1.0" min="0" max="2.0" category="Material"/> + <Property formalName="Green" name="green_weight" type="Float" default="1.0" min="0" max="2.0" category="Material"/> + <Property formalName="Blue" name="blue_weight" type="Float" default="1.0" min="0" max="2.0" category="Material"/> + <Property formalName="Base Color" name="basecolor" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" category="Material"/> + </MetaData> + <Shaders type="GLSL" version="330"> + <Shader> + <Shared></Shared> + <VertexShader> + </VertexShader> + <FragmentShader> +#define QT3DS_ENABLE_UV0 1 +#define QT3DS_ENABLE_WORLD_POSITION 1 +#define QT3DS_ENABLE_TEXTAN 0 +#define QT3DS_ENABLE_BINORMAL 0 + +#include "vertexFragmentBase.glsllib" + +// set shader output +out vec4 fragColor; + +void main() +{ + vec4 c = texture(basecolor, varTexCoord0.xy); + c.rgb *= vec3(red_weight, green_weight, blue_weight); + fragColor = c; +} + </FragmentShader> + </Shader> + </Shaders> + <Passes> + <ShaderKey value="7"/> + <LayerKey count="1"/> + <Pass> + </Pass> + </Passes> +</Material> diff --git a/examples/studio3d/dynamicloading/presentation/presentations/dynamicloading.uip b/examples/studio3d/dynamicloading/presentation/presentations/dynamicloading.uip new file mode 100644 index 0000000..bcde630 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/presentations/dynamicloading.uip @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<UIP version="6" > + <Project > + <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="1080" maintainAspect="False" preferKtx="False" > + <CustomColors count="16" >#989898 #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors> + </ProjectSettings> + <Classes > + <Effect id="FullScreenTextureOverlay_u46878" name="FullScreenTextureOverlay" sourcepath="../effects/FullScreenTextureOverlay.effect" /> + <CustomMaterial id="simplecustom_u34209" name="simplecustom" sourcepath="../materials/simplecustom.material" /> + </Classes> + <Graph > + <Scene id="Scene_u58399" backgroundcolor="0.596078 0.596078 0.596078 1" bgcolorenable="True" > + <Layer id="Layer2_u19717" variants="" > + <Camera id="Camera_u13977" /> + <Light id="Light_u36115" /> + </Layer> + <Layer id="Layer_u59613" variants="" > + <Effect id="FullScreenTextureOverlay_u35802" class="#FullScreenTextureOverlay_u46878" /> + <Model id="Cone_u21790" variants="" > + <Material id="Default_u13810" > + <Image id="Default_u13810_u63711" /> + </Material> + </Model> + <Camera id="Camera_u44253" /> + <Light id="Light_u28004" /> + <Model id="Cylinder_u21298" variants="" > + <Material id="Default_u37173" > + <Image id="Default_u37173_u19494" /> + </Material> + </Model> + <Model id="Sphere_u7999" variants="" > + <Material id="Default_u28670" > + <Image id="Default_u28670_u18741" /> + </Material> + </Model> + <Model id="Rectangle_u65276" variants="" > + <CustomMaterial id="Default_u12553" name="Default" class="#simplecustom_u34209" /> + </Model> + </Layer> + </Scene> + </Graph> + <Logic > + <State name="Master Slide" component="#Scene_u58399" > + <Add ref="#Layer_u59613" background="Transparent" backgroundcolor="0.596078 0.596078 0.596078 0.490196" disabledepthprepass="True" /> + <Add ref="#Camera_u44253" /> + <Add ref="#Light_u28004" /> + <State id="Slide1_u5883" name="Slide1" playmode="Play Through To..." > + <Set ref="#Layer_u59613" endtime="2000" /> + <Set ref="#Camera_u44253" endtime="2000" /> + <Set ref="#Light_u28004" endtime="2000" /> + <Add ref="#FullScreenTextureOverlay_u35802" name="FullScreenTextureOverlay" Overlay="../maps/Metal_Streaks.png" alpha="0.19" endtime="2000" overlay_repeat="1" > + <AnimationTrack property="alpha" type="EaseInOut" >0 0.01 100 100 0.616 0.26 100 100 2 0.09 100 100</AnimationTrack> + </Add> + <Add ref="#Cylinder_u21298" name="Cylinder" endtime="2000" scale="3 4 1" sourcepath="#Cylinder" /> + <Add ref="#Default_u37173" name="Default_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 1 1 1" diffuselightwrap="0" diffusemap="#Default_u37173_u19494" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" /> + <Add ref="#Default_u37173_u19494" sourcepath="../maps/Abstract_001_COLOR.jpg" subpresentation="" /> + </State> + <State id="Scene-Slide2_u11666" name="Slide2" playmode="Play Through To..." playthroughto="Next" > + <Set ref="#Layer_u59613" endtime="2000" /> + <Set ref="#Camera_u44253" endtime="2000" /> + <Set ref="#Light_u28004" endtime="2000" /> + <Add ref="#Layer2_u19717" name="Layer2" disabledepthprepass="False" endtime="2000" height="766" heightunits="pixels" sourcepath="subpres" top="29" width="1920" widthunits="pixels" /> + <Add ref="#Camera_u13977" endtime="2000" /> + <Add ref="#Light_u36115" endtime="2000" /> + <Add ref="#Cone_u21790" name="Cone" endtime="2000" position="-351.477 228.116 -4.69186" rotation="265 0 0" scale="2 2 2" sourcepath="#Cone" /> + <Add ref="#Default_u13810" name="Default_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 1 1 1" diffuselightwrap="0" diffusemap="#Default_u13810_u63711" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" /> + <Add ref="#Default_u13810_u63711" sourcepath="../maps/Blue_Marble_002_COLOR.jpg" subpresentation="" /> + <Add ref="#Sphere_u7999" name="Sphere" endtime="2000" position="204.727 229.668 0" scale="3 3 3" sourcepath="#Sphere" /> + <Add ref="#Default_u28670" name="Default_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 1 1 1" diffuselightwrap="0" diffusemap="#Default_u28670_u18741" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" /> + <Add ref="#Default_u28670_u18741" sourcepath="../maps/Ice_002_COLOR.jpg" subpresentation="" /> + </State> + <State id="Slide7_u8989" name="Slide3" playmode="Play Through To..." playthroughto="#Slide1_u5883" > + <Set ref="#Layer_u59613" endtime="2000" /> + <Set ref="#Camera_u44253" endtime="2000" /> + <Set ref="#Light_u28004" endtime="2000" /> + <Add ref="#Rectangle_u65276" name="Rectangle" endtime="2000" position="0 0 600" rotation="0 122 58" scale="8 8 8" shadowcaster="True" sourcepath="#Cube" /> + <Add ref="#Default_u12553" name="Default" basecolor="../maps/Rock_023_COLOR2.jpg" blue_weight="0.5" green_weight="0.68" red_weight="1.16" > + <AnimationTrack property="blue_weight" type="EaseInOut" >0 1.08 100 100 1.016 1.58 100 100 2 1.68 100 100</AnimationTrack> + <AnimationTrack property="green_weight" type="EaseInOut" >0 1.22 100 100 1.016 1.7 100 100 2 1.28 100 100</AnimationTrack> + <AnimationTrack property="red_weight" type="EaseInOut" >0 0.42 100 100 1.016 1.12 100 100 2 0.72 100 100</AnimationTrack> + </Add> + </State> + </State> + </Logic> + </Project> +</UIP> diff --git a/examples/studio3d/dynamicloading/presentation/presentations/subpres.uip b/examples/studio3d/dynamicloading/presentation/presentations/subpres.uip new file mode 100644 index 0000000..6b3d8d8 --- /dev/null +++ b/examples/studio3d/dynamicloading/presentation/presentations/subpres.uip @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<UIP version="6" > + <Project > + <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="766" maintainAspect="False" preferKtx="False" > + <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors> + </ProjectSettings> + <Graph > + <Scene id="Scene_u37264" backgroundcolor="0.521569 0.521569 0.521569 1" > + <Layer id="Layer_u43190" variants="" > + <Camera id="Camera_u16495" /> + <Light id="Light_u5451" /> + <Text id="Text_u23736" variants="" /> + <Model id="Rectangle_u54300" variants="" > + <Material id="Default_u22440" > + <Image id="Default_u22440_u62290" /> + </Material> + </Model> + </Layer> + </Scene> + </Graph> + <Logic > + <State name="Master Slide" component="#Scene_u37264" > + <Add ref="#Layer_u43190" /> + <Add ref="#Camera_u16495" /> + <Add ref="#Light_u5451" /> + <State id="Scene-Slide1_u45302" name="Slide1" > + <Add ref="#Text_u23736" name="Text" font="TitilliumWeb-Regular" position="-731.712 313.849 0" textstring="Subpresentation" /> + <Add ref="#Rectangle_u54300" name="Rectangle" scale="8 8 1" sourcepath="#Rectangle" /> + <Add ref="#Default_u22440" name="Default_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 1 1 1" diffuselightwrap="0" diffusemap="#Default_u22440_u62290" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" /> + <Add ref="#Default_u22440_u62290" sourcepath="../maps/Moon_001_COLOR.jpg" subpresentation="" /> + </State> + </State> + </Logic> + </Project> +</UIP> diff --git a/examples/studio3d/dynamicloading/qml.qrc b/examples/studio3d/dynamicloading/qml.qrc new file mode 100644 index 0000000..b4de469 --- /dev/null +++ b/examples/studio3d/dynamicloading/qml.qrc @@ -0,0 +1,19 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + <file>StartupProgress.qml</file> + <file>presentation/effects/FullScreenTextureOverlay.effect</file> + <file>presentation/fonts/TitilliumWeb-Regular.ttf</file> + <file>presentation/maps/Abstract_001_COLOR.jpg</file> + <file>presentation/maps/Blue_Marble_002_COLOR.jpg</file> + <file>presentation/maps/Ice_002_COLOR.jpg</file> + <file>presentation/maps/license.txt</file> + <file>presentation/maps/Metal_Streaks.png</file> + <file>presentation/maps/Moon_001_COLOR.jpg</file> + <file>presentation/maps/Rock_023_COLOR2.jpg</file> + <file>presentation/materials/simplecustom.material</file> + <file>presentation/presentations/dynamicloading.uip</file> + <file>presentation/presentations/subpres.uip</file> + <file>presentation/dynamicloading.uia</file> + </qresource> +</RCC> diff --git a/examples/studio3d/simpleqml/main.cpp b/examples/studio3d/simpleqml/main.cpp index f2640b5..7fe9bfb 100644 --- a/examples/studio3d/simpleqml/main.cpp +++ b/examples/studio3d/simpleqml/main.cpp @@ -55,6 +55,9 @@ int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setOrganizationName("The Qt Company"); + QCoreApplication::setOrganizationDomain("qt.io"); + QCoreApplication::setApplicationName("SimpleQml"); qputenv("QSG_INFO", "1"); QApplication app(argc, argv); diff --git a/examples/studio3d/simpleqml/main.qml b/examples/studio3d/simpleqml/main.qml index ed0278e..abdcb79 100644 --- a/examples/studio3d/simpleqml/main.qml +++ b/examples/studio3d/simpleqml/main.qml @@ -53,7 +53,7 @@ import QtStudio3D.OpenGL 2.4 import QtQuick.Window 2.3 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 -import Qt.labs.platform 1.0 +import QtQuick.Dialogs 1.3 Rectangle { id: root @@ -286,8 +286,10 @@ Rectangle { FileDialog { id: openDialog - fileMode: FileDialog.OpenFile nameFilters: ["UIP files (*.uip)", "UIA files (*.uia)", "All files (*)"] - onAccepted: s3dpres.source = file + selectExisting: true + selectFolder: false + selectMultiple: false + onAccepted: s3dpres.source = fileUrl } } diff --git a/examples/studio3d/studio3d.pro b/examples/studio3d/studio3d.pro index 05213bd..4eb7780 100644 --- a/examples/studio3d/studio3d.pro +++ b/examples/studio3d/studio3d.pro @@ -6,5 +6,6 @@ SUBDIRS += \ qtHaveModule(quick) { SUBDIRS += simpleqml \ qmldatainput \ - dynamicelement + dynamicelement \ + dynamicloading } diff --git a/res/DataModelMetadata/en-us/MetaData.xml b/res/DataModelMetadata/en-us/MetaData.xml index c3e0d6f..e249d22 100644 --- a/res/DataModelMetadata/en-us/MetaData.xml +++ b/res/DataModelMetadata/en-us/MetaData.xml @@ -153,6 +153,7 @@ <Material> <Property name="shaderlighting" formalName="Lighting" default="Pixel" category="Material" description="Light model" list="Pixel:None" /> <Property name="blendmode" formalName="Blending Mode" default="Normal" category="Material" description="How this material blends with content\nbehind it. Modes marked with * are\navailable only with HW supporting\nadvanced blending modes." list="Normal:Screen:Multiply:*Overlay:*ColorBurn:*ColorDodge" /> + <Property name="transparencymode" formalName="Transparency Mode" default="Default" category="Material" description="Material can be forced to be treated as transparent or opaque. Default behavior depends on the texture transparencies." list="Default:Force Transparent:Force Opaque" animatable="False" /> <Property name="vertexcolors" formalName="Enable Vertex Colors" type="Boolean" default="False" category="Material" description="Use vertex colors from the mesh" animatable="False" /> <Property name="diffuse" formalName="Diffuse Color" type="Color" default="1 1 1 1" category="Material" description="Color when lit from any direction" /> <Property name="diffusemap" formalName="Diffuse Map" type="Image" category="Material" description="Image to multiply with diffuse color" /> @@ -172,7 +173,6 @@ <Property name="bumpamount" formalName="Bump Amount" type="float" default=".5" category="Material" description="Strength of bump/normal map effect" /> <Property name="displacementmap" formalName="Displacement Map" type="Image" category="Material" description="Grayscale image used to offset vertices\nof the geometry" /> <Property name="displaceamount" formalName="Displacement Amount" type="float" default="20" category="Material" description="Distance to offset vertices" /> - <Property name="transparencymode" formalName="Transparency Mode" default="Default" category="Material" description="Material can be forced to be treated as transparent or opaque. Default behavior depends on the texture transparencies." list="Default:Force Transparent:Force Opaque" animatable="False" /> <Property name="opacity" formalName="Opacity" min="0" max="100" default="100" category="Material" description="Visibility of the geometry for this material." /> <Property name="opacitymap" formalName="Opacity Map" type="Image" category="Material" description="Image to vary the opacity across the material" /> <Property name="emissivecolor" formalName="Emissive Color" type="Color" default="1 1 1 1" category="Material" description="Color of self-illumination for this material" /> @@ -396,7 +396,7 @@ <Property name="shdwfactor" formalName="Shadow Darkness" description="Factor used to darken shadows" default="10.0" min="1.0" max="100.0" category="Shadow" /> <Property name="shdwfilter" formalName="Shadow Softness" description="Width of the blur filter on the shadow map" min="1" max="100" default="35" category="Shadow" /> <Property name="shdwmapres" formalName="Shadow Resolution" description="Resolution of shadow map\n(powers of two)" type="ShadowMapResolution" default="9" animatable="False" category="Shadow" /> - <Property name="shdwbias" formalName="Shadow Depth Bias" description="Slight offset to avoid self-shadowing\nartifacts" default="0" min="-1.0" max="1.0" category="Shadow" /> + <Property name="shdwbias" formalName="Shadow Depth Bias" description="Slight offset to avoid self-shadowing\nartifacts" default="0" min="-0.1" max="0.1" decimals="3" category="Shadow" /> <Property name="shdwmapfar" formalName="Shadow Far Clip" description="Affects the maximum distance for the shadow\ndepth map" default="5000" category="Shadow" /> <Property name="shdwmapfov" formalName="Shadow Field of View" description="Affects the field of view of the shadow\ncamera" default="90" min="1" max="179" hidden="True" category="Shadow" /> diff --git a/src/api/studio3d/doc/src/examples.qdoc b/src/api/studio3d/doc/src/examples.qdoc index f7a78b4..bb655d8 100644 --- a/src/api/studio3d/doc/src/examples.qdoc +++ b/src/api/studio3d/doc/src/examples.qdoc @@ -29,13 +29,23 @@ \title Examples \ingroup examples \page qt3dstudio-opengl-runtime-examples.html + \noautolist Included in the \RUNTIME you will find a set of examples. These are located in the \c {examples} folder in the installation folder. + \section1 QML Examples + + \list + \li \l {Qt 3D Studio Runtime: Simple QML Example} + \li \l {Qt 3D Studio Runtime: QML DataInput Example} + \li \l {Qt 3D Studio Runtime: Dynamic Loading Example} + \endlist + \section1 More Examples You can find more examples from \l{https://git.qt.io/public-demos/qt3dstudio}, these examples are more visually appealing and suitable to use as demos for example. + */ diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp index 0536310..05e2e8e 100644 --- a/src/api/studio3d/q3dspresentation.cpp +++ b/src/api/studio3d/q3dspresentation.cpp @@ -613,6 +613,7 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath) /*! \qmlmethod Presentation::exportShaderCache(url shaderCacheFile, bool binaryShaders) + \since QtStudio3D.OpenGL 2.5 Writes the shaders currently in use to the file specified by \a shaderCacheFile URL. If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise, @@ -631,6 +632,7 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath) \sa shaderCacheFile, shaderCacheExported */ /*! + \since Qt 3D Studio 2.5 Writes the shaders currently in use to the file specified by \a shaderCacheFile URL. If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise, the shader source code is exported. @@ -657,6 +659,7 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar /*! \qmlmethod Presentation::exportShaderCache(bool binaryShaders) + \since QtStudio3D.OpenGL 2.5 Exports the shaders currently in use and dumps the resulting cache encoded with base64 into stderr. This function is provided as a means to extract the shader cache from environments @@ -680,6 +683,7 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar \sa shaderCacheFile, shaderCacheExported */ /*! + \since Qt 3D Studio 2.5 Exports the shaders currently in use and dumps the resulting cache encoded with base64 into stderr. This function is provided as a means to extract the shader cache from environments without a writable disk. The base64 output needs to be converted back to binary @@ -707,6 +711,7 @@ void Q3DSPresentation::exportShaderCache(bool binaryShaders) /*! \qmlproperty url Presentation::shaderCacheFile + \since QtStudio3D.OpenGL 2.5 Specifies the shader cache file to be used for initial shader initialization. This property value must be set before the presentation is shown. @@ -722,6 +727,7 @@ void Q3DSPresentation::exportShaderCache(bool binaryShaders) \sa exportShaderCache(), shaderCacheExport */ /*! + \since Qt 3D Studio 2.5 Specifies the shader cache file to be used for initial shader initialization. This property value must be set before the presentation is shown. Using cached shaders improves presentation initialization speed. @@ -750,6 +756,7 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName) /*! \qmlsignal Presentation::shaderCacheExported(bool success) + \since QtStudio3D.OpenGL 2.5 Emitted when a shader cache export is completed. The parameter \a success indicates whether or not the export was successful. @@ -759,6 +766,7 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName) /*! \fn Q3DSPresentation::shaderCacheExported(bool success) + \since Qt 3D Studio 2.5 Emitted when a shader cache export is completed. The parameter \a success indicates whether or not the export was successful. @@ -941,6 +949,7 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a } /*! + \since Qt 3D Studio 2.5 Sets the \a provider to use for images requested via the \e image: url scheme, with host \a providerId. The runtime takes ownership of \a provider. @@ -959,6 +968,22 @@ void Q3DSPresentation::addImageProvider(const QString &providerId, QQmlImageProv } /*! + \since Qt 3D Studio 2.5 + Returns the OpenGL texture id associated with a layer or an image specified + by \a elementPath. + + For example, \c{Scene.Layer} returns the texture id of a layer while + \c{Scene.Layer.Rectangle.Material.diffusemap} returns the texture id of + an image or a subpresentation. + */ +uint Q3DSPresentation::textureId(const QString &elementPath) +{ + if (d_ptr->m_viewerApp) + return d_ptr->m_viewerApp->textureId(elementPath); + return 0; +} + +/*! Activate or deactivate the presentation identified by \a id depending on the value of \a active. */ diff --git a/src/api/studio3d/q3dspresentation.h b/src/api/studio3d/q3dspresentation.h index 1c53f98..5210a29 100644 --- a/src/api/studio3d/q3dspresentation.h +++ b/src/api/studio3d/q3dspresentation.h @@ -59,7 +59,7 @@ class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject Q_PROPERTY(QStringList createdElements READ createdElements NOTIFY elementsCreated) Q_PROPERTY(QStringList createdMaterials READ createdMaterials NOTIFY materialsCreated) Q_PROPERTY(QStringList createdMeshes READ createdMeshes NOTIFY meshesCreated) - Q_PROPERTY(QUrl shaderCacheFile READ shaderCacheFile WRITE setShaderCacheFile NOTIFY shaderCacheFileChanged ) + Q_PROPERTY(QUrl shaderCacheFile READ shaderCacheFile WRITE setShaderCacheFile NOTIFY shaderCacheFileChanged REVISION 1) public: explicit Q3DSPresentation(QObject *parent = nullptr); @@ -92,8 +92,9 @@ public: Q_INVOKABLE void preloadSlide(const QString &elementPath); Q_INVOKABLE void unloadSlide(const QString &elementPath); - Q_INVOKABLE void exportShaderCache(const QUrl &shaderCacheFile, bool binaryShaders); - Q_INVOKABLE void exportShaderCache(bool binaryShaders); + Q_REVISION(1) Q_INVOKABLE void exportShaderCache(const QUrl &shaderCacheFile, + bool binaryShaders); + Q_REVISION(1) Q_INVOKABLE void exportShaderCache(bool binaryShaders); QUrl shaderCacheFile() const; // Input event handlers @@ -126,6 +127,8 @@ public: void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider); + uint textureId(const QString &elementPath); + public Q_SLOTS: void setSource(const QUrl &source); void setVariantList(const QStringList &variantList); diff --git a/src/api/studio3d/q3dssurfaceviewer.cpp b/src/api/studio3d/q3dssurfaceviewer.cpp index e885a4b..401cb8f 100644 --- a/src/api/studio3d/q3dssurfaceviewer.cpp +++ b/src/api/studio3d/q3dssurfaceviewer.cpp @@ -534,6 +534,8 @@ void Q3DSSurfaceViewerPrivate::update() m_viewerApp->Render(); + Q_EMIT q_ptr->afterRendering(); + const uint defaultFbo = m_context->defaultFramebufferObject(); if (m_surface->surfaceClass() == QSurface::Window && m_fboId == defaultFbo) diff --git a/src/api/studio3d/q3dssurfaceviewer.h b/src/api/studio3d/q3dssurfaceviewer.h index 42be5c2..b9e4016 100644 --- a/src/api/studio3d/q3dssurfaceviewer.h +++ b/src/api/studio3d/q3dssurfaceviewer.h @@ -100,6 +100,7 @@ Q_SIGNALS: void presentationLoaded(); void presentationReady(); void frameUpdate(); + void afterRendering(); void errorChanged(); void presentationIdChanged(const QString &id); diff --git a/src/api/studio3d/q3dsviewersettings.cpp b/src/api/studio3d/q3dsviewersettings.cpp index ead4eb9..88d1d50 100644 --- a/src/api/studio3d/q3dsviewersettings.cpp +++ b/src/api/studio3d/q3dsviewersettings.cpp @@ -231,7 +231,7 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode) /*! \qmlproperty enumeration ViewerSettings::stereoMode - \since Qt 3D Studio 2.5 + \since QtStudio3D.OpenGL 2.5 Specifies the stereo mode. The default value \c is StereoModeMono where the view is rendered normally, as suitable for 2D displays. Other available modes @@ -240,6 +240,8 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode) \value StereoModeMono Renders presentation normally in mono. \value StereoModeTopBottom Renders presentation in stereoscopic top-bottom mode. \value StereoModeLeftRight Renders presentation in stereoscopic left-right mode. + \value StereoModeAnaglyphRedCyan Renders presentation in anaglyph red-cyan mode. + \value StereoModeAnaglyphGreenMagenta Renders presentation in anaglyph green-magenta mode. The default value is \c{StereoModeMono}. */ @@ -255,6 +257,8 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode) \value StereoModeMono Renders presentation normally in mono. \value StereoModeTopBottom Renders presentation in stereoscopic top-bottom mode. \value StereoModeLeftRight Renders presentation in stereoscopic left-right mode. + \value StereoModeAnaglyphRedCyan Renders presentation in anaglyph red-cyan mode. + \value StereoModeAnaglyphGreenMagenta Renders presentation in anaglyph green-magenta mode. The default value is \c{StereoModeMono}. */ @@ -272,6 +276,19 @@ void Q3DSViewerSettings::setStereoMode(Q3DSViewerSettings::StereoMode mode) } /*! + \qmlproperty real ViewerSettings::stereoEyeSeparation + + \since QtStudio3D.OpenGL 2.5 + + Specifies the eye (camera) separation of stereo rendering. + Value is the amount left and right eye cameras move in x-coordinate + values away from center. Bigger separation increases the 3D effect. + Optimal value depends on viewed presentation. + + This has only effect when stereo mode is set to something else than + default \c{StereoModeMono}. + */ +/*! \property Q3DSViewerSettings::stereoEyeSeparation \since Qt 3D Studio 2.5 @@ -516,8 +533,12 @@ void Q3DSViewerSettingsPrivate::setStereoMode(Q3DSViewerSettings::StereoMode mod m_viewerApp->SetStereoMode(Q3DSViewer::ViewerStereoModes::Mono); else if (mode == Q3DSViewerSettings::StereoModeTopBottom) m_viewerApp->SetStereoMode(Q3DSViewer::ViewerStereoModes::TopBottom); - else + else if (mode == Q3DSViewerSettings::StereoModeLeftRight) m_viewerApp->SetStereoMode(Q3DSViewer::ViewerStereoModes::LeftRight); + else if (mode == Q3DSViewerSettings::StereoModeAnaglyphRedCyan) + m_viewerApp->SetStereoMode(Q3DSViewer::ViewerStereoModes::AnaglyphRedCyan); + else + m_viewerApp->SetStereoMode(Q3DSViewer::ViewerStereoModes::AnaglyphGreenMagenta); } else if (m_commandQueue) { m_commandQueue->m_stereoMode = mode; m_commandQueue->m_stereoModeChanged = true; diff --git a/src/api/studio3d/q3dsviewersettings.h b/src/api/studio3d/q3dsviewersettings.h index 0d78e1b..0a5e699 100644 --- a/src/api/studio3d/q3dsviewersettings.h +++ b/src/api/studio3d/q3dsviewersettings.h @@ -50,8 +50,8 @@ class Q_STUDIO3D_EXPORT Q3DSViewerSettings : public QObject Q_PROPERTY(QColor matteColor READ matteColor WRITE setMatteColor NOTIFY matteColorChanged) Q_PROPERTY(bool showRenderStats READ isShowRenderStats WRITE setShowRenderStats NOTIFY showRenderStatsChanged) Q_PROPERTY(ScaleMode scaleMode READ scaleMode WRITE setScaleMode NOTIFY scaleModeChanged) - Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode NOTIFY stereoModeChanged) - Q_PROPERTY(double stereoEyeSeparation READ stereoEyeSeparation WRITE setStereoEyeSeparation NOTIFY stereoEyeSeparationChanged) + Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode NOTIFY stereoModeChanged REVISION 1) + Q_PROPERTY(double stereoEyeSeparation READ stereoEyeSeparation WRITE setStereoEyeSeparation NOTIFY stereoEyeSeparationChanged REVISION 1) public: enum ShadeMode { @@ -68,7 +68,9 @@ public: enum StereoMode { StereoModeMono, StereoModeTopBottom, - StereoModeLeftRight + StereoModeLeftRight, + StereoModeAnaglyphRedCyan, + StereoModeAnaglyphGreenMagenta }; explicit Q3DSViewerSettings(QObject *parent = nullptr); diff --git a/src/api/studio3d/studio3d.pro b/src/api/studio3d/studio3d.pro index 6749a57..f0cd874 100644 --- a/src/api/studio3d/studio3d.pro +++ b/src/api/studio3d/studio3d.pro @@ -51,7 +51,8 @@ SOURCES += q3dsdataoutput.cpp \ q3dsimagesequencegenerator.cpp \ q3dsimagesequencegeneratorthread.cpp \ q3dsdatainput.cpp \ - q3dsgeometry.cpp + q3dsgeometry.cpp \ + ../../foundation/Qt3DSLogging.cpp # Platform specific surface format discovery functions #TODO: QT3DS-3608 Implement OpenGL version discovery for Windows diff --git a/src/api/studio3dqml/plugins.qmltypes b/src/api/studio3dqml/plugins.qmltypes index bb8f052..a1d360d 100644 --- a/src/api/studio3dqml/plugins.qmltypes +++ b/src/api/studio3dqml/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtStudio3D.OpenGL 2.4' +// 'qmlplugindump -nonrelocatable QtStudio3D.OpenGL 2.5' Module { dependencies: ["QtQuick 2.12"] @@ -25,6 +25,11 @@ Module { Method { name: "setValue" Parameter { name: "value"; type: "QVariant" } + Parameter { name: "force"; type: "bool" } + } + Method { + name: "setValue" + Parameter { name: "value"; type: "QVariant" } } Method { name: "metadata" @@ -85,6 +90,7 @@ Module { Property { name: "createdElements"; type: "QStringList"; isReadonly: true } Property { name: "createdMaterials"; type: "QStringList"; isReadonly: true } Property { name: "createdMeshes"; type: "QStringList"; isReadonly: true } + Property { name: "shaderCacheFile"; revision: 1; type: "QUrl" } Signal { name: "variantListChanged" Parameter { name: "variantList"; type: "QStringList" } @@ -131,6 +137,14 @@ Module { Parameter { name: "meshNames"; type: "QStringList" } Parameter { name: "error"; type: "string" } } + Signal { + name: "shaderCacheFileChanged" + Parameter { name: "fileName"; type: "QUrl" } + } + Signal { + name: "shaderCacheExported" + Parameter { name: "success"; type: "bool" } + } Method { name: "setSource" Parameter { name: "source"; type: "QUrl" } @@ -184,13 +198,17 @@ Module { name: "setDataInputValue" Parameter { name: "name"; type: "string" } Parameter { name: "value"; type: "QVariant" } - Parameter { name: "valueRole"; type: "Q3DSDataInput::ValueRole" } + Parameter { name: "force"; type: "bool" } } Method { name: "setDataInputValue" Parameter { name: "name"; type: "string" } Parameter { name: "value"; type: "QVariant" } } + Method { + name: "setShaderCacheFile" + Parameter { name: "fileName"; type: "QUrl" } + } Method { name: "getDataInputs"; type: "QVariantList" } Method { name: "getDataInputs" @@ -206,13 +224,27 @@ Module { name: "unloadSlide" Parameter { name: "elementPath"; type: "string" } } + Method { + name: "exportShaderCache" + revision: 1 + Parameter { name: "shaderCacheFile"; type: "QUrl" } + Parameter { name: "binaryShaders"; type: "bool" } + } + Method { + name: "exportShaderCache" + revision: 1 + Parameter { name: "binaryShaders"; type: "bool" } + } } Component { name: "Q3DSPresentationItem" defaultProperty: "qmlChildren" prototype: "Q3DSPresentation" - exports: ["QtStudio3D.OpenGL/Presentation 2.4"] - exportMetaObjectRevisions: [0] + exports: [ + "QtStudio3D.OpenGL/Presentation 2.4", + "QtStudio3D.OpenGL/Presentation 2.5" + ] + exportMetaObjectRevisions: [0, 0] Property { name: "qmlChildren"; type: "QObject"; isList: true; isReadonly: true } Method { name: "appendQmlChildren" @@ -292,8 +324,11 @@ Module { name: "Q3DSStudio3D" defaultProperty: "data" prototype: "QQuickFramebufferObject" - exports: ["QtStudio3D.OpenGL/Studio3D 2.4"] - exportMetaObjectRevisions: [0] + exports: [ + "QtStudio3D.OpenGL/Studio3D 2.4", + "QtStudio3D.OpenGL/Studio3D 2.5" + ] + exportMetaObjectRevisions: [0, 0] Enum { name: "EventIgnoreFlags" values: { @@ -309,6 +344,7 @@ Module { Property { name: "viewerSettings"; type: "Q3DSViewerSettings"; isReadonly: true; isPointer: true } Property { name: "error"; type: "string"; isReadonly: true } Property { name: "ignoredEvents"; type: "EventIgnoreFlags" } + Property { name: "asyncInit"; revision: 1; type: "bool" } Signal { name: "frameUpdate" } Signal { name: "runningChanged" @@ -320,6 +356,10 @@ Module { } Signal { name: "presentationReady" } Signal { name: "presentationLoaded" } + Signal { + name: "asyncInitChanged" + Parameter { name: "enabled"; type: "bool" } + } Method { name: "reset" } } Component { @@ -332,8 +372,11 @@ Module { Component { name: "Q3DSViewerSettings" prototype: "QObject" - exports: ["QtStudio3D.OpenGL/ViewerSettings 2.4"] - exportMetaObjectRevisions: [0] + exports: [ + "QtStudio3D.OpenGL/ViewerSettings 2.4", + "QtStudio3D.OpenGL/ViewerSettings 2.5" + ] + exportMetaObjectRevisions: [0, 0] Enum { name: "ShadeMode" values: { @@ -349,10 +392,20 @@ Module { "ScaleModeCenter": 2 } } + Enum { + name: "StereoMode" + values: { + "StereoModeMono": 0, + "StereoModeTopBottom": 1, + "StereoModeLeftRight": 2 + } + } Property { name: "matteEnabled"; type: "bool" } Property { name: "matteColor"; type: "QColor" } Property { name: "showRenderStats"; type: "bool" } Property { name: "scaleMode"; type: "ScaleMode" } + Property { name: "stereoMode"; revision: 1; type: "StereoMode" } + Property { name: "stereoEyeSeparation"; revision: 1; type: "double" } Signal { name: "matteEnabledChanged" Parameter { name: "enabled"; type: "bool" } @@ -373,6 +426,14 @@ Module { name: "scaleModeChanged" Parameter { name: "mode"; type: "ScaleMode" } } + Signal { + name: "stereoModeChanged" + Parameter { name: "mode"; type: "StereoMode" } + } + Signal { + name: "stereoEyeSeparationChanged" + Parameter { name: "separation"; type: "double" } + } Method { name: "setMatteEnabled" Parameter { name: "enabled"; type: "bool" } @@ -390,6 +451,14 @@ Module { Parameter { name: "mode"; type: "ScaleMode" } } Method { + name: "setStereoMode" + Parameter { name: "mode"; type: "StereoMode" } + } + Method { + name: "setStereoEyeSeparation" + Parameter { name: "separation"; type: "double" } + } + Method { name: "save" Parameter { name: "group"; type: "string" } Parameter { name: "organization"; type: "string" } diff --git a/src/api/studio3dqml/q3dsplugin.cpp b/src/api/studio3dqml/q3dsplugin.cpp index 640018f..8a01141 100644 --- a/src/api/studio3dqml/q3dsplugin.cpp +++ b/src/api/studio3dqml/q3dsplugin.cpp @@ -57,6 +57,11 @@ void Q3DSPlugin::registerTypes(const char *uri) qmlRegisterType<Q3DSSubPresentationSettings>(uri, 2, 4, "SubPresentationSettings"); qmlRegisterType<Q3DSDataInput>(uri, 2, 4, "DataInput"); qmlRegisterType<Q3DSDataOutput>(uri, 2, 4, "DataOutput"); + + // 2.5 + qmlRegisterType<Q3DSStudio3D, 1>(uri, 2, 5, "Studio3D"); + qmlRegisterType<Q3DSViewerSettings, 1>(uri, 2, 5, "ViewerSettings"); + qmlRegisterType<Q3DSPresentationItem, 1>(uri, 2, 5, "Presentation"); } QT_END_NAMESPACE diff --git a/src/api/studio3dqml/q3dsstudio3d.cpp b/src/api/studio3dqml/q3dsstudio3d.cpp index 4cb0850..f1e383f 100644 --- a/src/api/studio3dqml/q3dsstudio3d.cpp +++ b/src/api/studio3dqml/q3dsstudio3d.cpp @@ -214,6 +214,7 @@ void Q3DSStudio3D::setError(const QString &error) /*! \qmlproperty bool Studio3D::asyncInit + \since QtStudio3D.OpenGL 2.5 If set to \c{true}, indicates that renderer initialization should be done asynchronously in a helper thread. This improves UI responsiveness while initialization is happening, diff --git a/src/api/studio3dqml/q3dsstudio3d_p.h b/src/api/studio3dqml/q3dsstudio3d_p.h index 963474c..1fd32fe 100644 --- a/src/api/studio3dqml/q3dsstudio3d_p.h +++ b/src/api/studio3dqml/q3dsstudio3d_p.h @@ -62,7 +62,7 @@ class Q3DSStudio3D : public QQuickFramebufferObject Q_PROPERTY(Q3DSViewerSettings *viewerSettings READ viewerSettings CONSTANT) Q_PROPERTY(QString error READ error NOTIFY errorChanged) Q_PROPERTY(EventIgnoreFlags ignoredEvents READ ignoredEvents WRITE setIgnoredEvents NOTIFY ignoredEventsChanged) - Q_PROPERTY(bool asyncInit READ asyncInit WRITE setAsyncInit NOTIFY asyncInitChanged) + Q_PROPERTY(bool asyncInit READ asyncInit WRITE setAsyncInit NOTIFY asyncInitChanged REVISION 1) public: enum EventIgnoreFlag { diff --git a/src/datamodel/Qt3DSMetadata.cpp b/src/datamodel/Qt3DSMetadata.cpp index a179bf6..83cefa7 100644 --- a/src/datamodel/Qt3DSMetadata.cpp +++ b/src/datamodel/Qt3DSMetadata.cpp @@ -831,11 +831,11 @@ public: } bool LoadEffectXMLFile(const char *inType, const char *inId, const char *inName, - const char *inSourcePath) override + const char *inSourcePath) override { const wchar_t *theType(Convert0(inType)); const wchar_t *theId(Convert1(inId)); - const wchar_t *theName(Convert2(inName)); + Q_UNUSED(inName) if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end()) return true; @@ -847,7 +847,7 @@ public: if (theStream) { std::vector<SMetaDataLoadWarning> warnings; bool success = m_NewMetaData->LoadEffectXMLFromSourcePath( - inSourcePath, theMaster, theName, warnings, *theStream); + inSourcePath, theMaster, theId, warnings, *theStream); (void)success; QT3DS_ASSERT(success); return success; @@ -856,12 +856,11 @@ public: } bool LoadMaterialXMLFile(const char *inType, const char *inId, const char *inName, - const char *inSourcePath) override + const char *inSourcePath) override { const wchar_t *theType(Convert0(inType)); const wchar_t *theId(Convert1(inId)); - const wchar_t *theName(Convert2(inName)); - (void)theName; + Q_UNUSED(inName) if (m_IdToHandleMap.find(theId) != m_IdToHandleMap.end()) return true; diff --git a/src/dm/systems/Qt3DSDMValue.cpp b/src/dm/systems/Qt3DSDMValue.cpp index 57ba400..48267c8 100644 --- a/src/dm/systems/Qt3DSDMValue.cpp +++ b/src/dm/systems/Qt3DSDMValue.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "Qt3DSDMPrefix.h" #include "Qt3DSDMValue.h" +#include "foundation/Qt3DSLogging.h" #include <QtGui/qcolor.h> #include <QtCore/qdebug.h> @@ -91,7 +92,7 @@ SValue::SValue(const QVariant &inData) break; } default: - qDebug() << "Add a handler for QVariant::type" << inData.type(); + qCWarning(qt3ds::WARNING) << "Add a handler for QVariant::type" << inData.type(); throw std::runtime_error("Cannot transform this QVariant into SValue"); } } @@ -124,7 +125,7 @@ QVariant SValue::toQVariant() const } case DataModelDataType::FloatList: { //KDAB_TODO - qDebug() << "Add a handler for type DataModelDataType::FloatList"; + qCWarning(qt3ds::WARNING) << "Add a handler for type DataModelDataType::FloatList"; return {}; } case DataModelDataType::Long4: { @@ -135,13 +136,10 @@ QVariant SValue::toQVariant() const switch (theRef.GetReferenceType()) { case ObjectReferenceType::Absolute: return SValue(get<SLong4>(theRef.m_Value)).toQVariant(); - break; case ObjectReferenceType::Relative: return SValue(get<TDataStrPtr>(theRef.m_Value)).toQVariant(); - break; case ObjectReferenceType::Unknown: return QVariant::fromValue(QVector<qt3ds::QT3DSU32>()); - break; } } case DataModelDataType::StringOrInt: { diff --git a/src/engine/Qt3DSRuntimeView.cpp b/src/engine/Qt3DSRuntimeView.cpp index c5448e3..76efaae 100644 --- a/src/engine/Qt3DSRuntimeView.cpp +++ b/src/engine/Qt3DSRuntimeView.cpp @@ -226,6 +226,7 @@ public: void createMesh(const QString &name, qt3dsimp::Mesh *mesh) override; void deleteMeshes(const QStringList &meshNames) override; void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) override; + uint textureId(const QString &elementPath) override; void SetAttribute(const char *elementPath, const char *attributeName, const char *value) override; bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override; @@ -743,6 +744,17 @@ void CRuntimeView::addImageProvider(const QString &providerId, QQmlImageProvider } } +uint CRuntimeView::textureId(const QString &elementPath) +{ + if (m_Application) { + Q3DStudio::CQmlEngine &theBridgeEngine + = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml()); + return theBridgeEngine.textureId(elementPath, + &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer()); + } + return 0; +} + void CRuntimeView::SetAttribute(const char *elementPath, const char *attributeName, const char *value) { diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h index 482e69a..e3f57d1 100644 --- a/src/engine/Qt3DSRuntimeView.h +++ b/src/engine/Qt3DSRuntimeView.h @@ -110,7 +110,9 @@ struct TegraRenderStereoModes enum Enum { Mono, TopBottom, - LeftRight + LeftRight, + AnaglyphRedCyan, + AnaglyphGreenMagenta }; }; @@ -227,6 +229,7 @@ public: virtual void createMesh(const QString &name, qt3dsimp::Mesh *mesh) = 0; virtual void deleteMeshes(const QStringList &meshNames) = 0; virtual void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) = 0; + virtual uint textureId(const QString &elementPath) = 0; virtual void SetAttribute(const char *elementPath, const char *attributeName, const char *value) = 0; virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0; diff --git a/src/foundation/qt/formatdiscovery.cpp b/src/foundation/qt/formatdiscovery.cpp index 0a4bcbd..db1e470 100644 --- a/src/foundation/qt/formatdiscovery.cpp +++ b/src/foundation/qt/formatdiscovery.cpp @@ -49,7 +49,7 @@ static QSurfaceFormat findIdealGLVersion() QOpenGLContext ctx; ctx.setFormat(fmt); if (ctx.create() && ctx.format().version() >= qMakePair(4, 3)) { - qDebug("Requesting OpenGL 4.3 core context succeeded"); + qCInfo(qt3ds::TRACE_INFO) << "Requesting OpenGL 4.3 core context succeeded"; return ctx.format(); } @@ -57,7 +57,7 @@ static QSurfaceFormat findIdealGLVersion() fmt.setVersion(3, 3); ctx.setFormat(fmt); if (ctx.create() && ctx.format().version() >= qMakePair(3, 3)) { - qDebug("Requesting OpenGL 3.3 core context succeeded"); + qCInfo(qt3ds::TRACE_INFO) << "Requesting OpenGL 3.3 core context succeeded"; return ctx.format(); } @@ -80,7 +80,7 @@ static QSurfaceFormat findIdealGLESVersion() // support and return a 3.0 context. This is against the spec since 3.0 is // obviously not backwards compatible with 3.1, but hey... if (ctx.create() && ctx.format().version() >= qMakePair(3, 1)) { - qDebug("Requesting OpenGL ES 3.1 context succeeded"); + qCInfo(qt3ds::TRACE_INFO) << "Requesting OpenGL ES 3.1 context succeeded"; return ctx.format(); } @@ -89,14 +89,14 @@ static QSurfaceFormat findIdealGLESVersion() fmt.setVersion(3, 0); ctx.setFormat(fmt); if (ctx.create() && ctx.format().version() >= qMakePair(3, 0)) { - qDebug("Requesting OpenGL ES 3.0 context succeeded"); + qCInfo(qt3ds::TRACE_INFO) << "Requesting OpenGL ES 3.0 context succeeded"; return ctx.format(); } fmt.setVersion(2, 0); ctx.setFormat(fmt); if (ctx.create()) { - qDebug("Requesting OpenGL ES 2.0 context succeeded"); + qCInfo(qt3ds::TRACE_INFO) << "Requesting OpenGL ES 2.0 context succeeded"; return fmt; } diff --git a/src/foundation/qt_attribution.json b/src/foundation/qt_attribution.json index 537d8be..46b571c 100644 --- a/src/foundation/qt_attribution.json +++ b/src/foundation/qt_attribution.json @@ -1,3 +1,4 @@ +[ { "Id": "convertutf", "Name": "ConvertUTF", @@ -7,8 +8,7 @@ "License": "Other", "LicenseFile": "LICENSE_CONVERTUTF.TXT", "Copyright": "Copyright 2001-2004 Unicode, Inc." -} -, +}, { "Id": "socket", "Name": "Socket", @@ -20,3 +20,4 @@ "LicenseFile": "LICENCE_SOCKET.TXT", "Copyright": "Copyright (C) 2004-2013 Diego Nehab." } +] diff --git a/src/render/Qt3DSRenderBaseTypes.h b/src/render/Qt3DSRenderBaseTypes.h index fa5e6fc..909077d 100644 --- a/src/render/Qt3DSRenderBaseTypes.h +++ b/src/render/Qt3DSRenderBaseTypes.h @@ -37,6 +37,7 @@ #include "foundation/Qt3DSSimpleTypes.h" #include "foundation/Qt3DSMath.h" #include "foundation/Qt3DSVec2.h" +#include <QtCore/qstring.h> namespace qt3ds { @@ -1077,6 +1078,8 @@ struct NVRenderVertFragCompilationResult NVRenderShaderProgram *mShader; ///< contains the program + QString errors; + NVRenderVertFragCompilationResult() : mShaderName("") , mShader(NULL) diff --git a/src/render/Qt3DSRenderShaderProgram.cpp b/src/render/Qt3DSRenderShaderProgram.cpp index cc8c1fd..b5f2a77 100644 --- a/src/render/Qt3DSRenderShaderProgram.cpp +++ b/src/render/Qt3DSRenderShaderProgram.cpp @@ -1115,20 +1115,23 @@ namespace render { if (!vertexValid || !fragValid || !tcValid || !teValid || !geValid || !bProgramIsValid) { NVFoundationBase &foundation(context.GetFoundation()); + const char *err; if (!vertexValid) { qCCritical(INTERNAL_ERROR, "Failed to generate vertex shader!!"); qCCritical(INTERNAL_ERROR, "Vertex source:\n%s", nonNull((const char *)vertShaderSource.begin())); - WriteErrorMessage(foundation, "Vertex compilation output:", - vtxShader.getValue()->GetErrorMessage()); + err = vtxShader.getValue()->GetErrorMessage(); + result.errors.append(err); + WriteErrorMessage(foundation, "Vertex compilation output:", err); } if (!fragValid) { qCCritical(INTERNAL_ERROR, "Failed to generate fragment shader!!"); qCCritical(INTERNAL_ERROR, "Fragment source:\n%s", nonNull((const char *)fragShaderSource.begin())); - WriteErrorMessage(foundation, "Fragment compilation output:", - fragShader.getValue()->GetErrorMessage()); + err = fragShader.getValue()->GetErrorMessage(); + result.errors.append(err); + WriteErrorMessage(foundation, "Fragment compilation output:", err); } if (!tcValid) { @@ -1136,8 +1139,9 @@ namespace render { "Failed to generate tessellation control shader!!"); qCCritical(INTERNAL_ERROR, "Tessellation control source:\n%s", nonNull((const char *)tessControlShaderSource.begin())); - WriteErrorMessage(foundation, "Tessellation control compilation output:", - tcShader.getValue()->GetErrorMessage()); + err = tcShader.getValue()->GetErrorMessage(); + result.errors.append(err); + WriteErrorMessage(foundation, "Tessellation control compilation output:", err); } if (!teValid) { @@ -1145,16 +1149,18 @@ namespace render { "Failed to generate tessellation evaluation shader!!"); qCCritical(INTERNAL_ERROR, "Tessellation evaluation source:\n%s", nonNull((const char *)tessEvaluationShaderSource.begin())); - WriteErrorMessage(foundation, "Tessellation evaluation compilation output:", - teShader.getValue()->GetErrorMessage()); + err = teShader.getValue()->GetErrorMessage(); + result.errors.append(err); + WriteErrorMessage(foundation, "Tessellation evaluation compilation output:", err); } if (!geValid) { qCCritical(INTERNAL_ERROR, "Failed to generate geometry shader!!"); qCCritical(INTERNAL_ERROR, "Geometry source:\n%s", nonNull((const char *)geometryShaderSource.begin())); - WriteErrorMessage(foundation, "Geometry compilation output:", - geShader.getValue()->GetErrorMessage()); + err = geShader.getValue()->GetErrorMessage(); + result.errors.append(err); + WriteErrorMessage(foundation, "Geometry compilation output:", err); } if (!bProgramIsValid && pProgram) { diff --git a/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp b/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp index 54d8d5d..718941e 100644 --- a/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp +++ b/src/render/backends/gl/Q3DSRenderBackendGLES2.cpp @@ -414,7 +414,6 @@ bool NVRenderBackendGLES2Impl::SetInputAssembler(NVRenderBackendInputAssemblerOb if (inputAssembler->m_cachedShaderHandle != programID) { GL_CALL_EXTENSION_FUNCTION(glBindVertexArrayOES(inputAssembler->m_VaoID)); - inputAssembler->m_cachedShaderHandle = programID; QT3DS_FOREACH(idx, shaderAttribBuffer.size()) { @@ -438,6 +437,9 @@ bool NVRenderBackendGLES2Impl::SetInputAssembler(NVRenderBackendInputAssemblerOb } } + // Cache the program id after checking for errors + inputAssembler->m_cachedShaderHandle = programID; + // disable max possible used first // this is currently sufficient since we always re-arrange input attributes from 0 for (QT3DSU32 i = 0; i < attribLayout->m_LayoutAttribEntries.size(); i++) diff --git a/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp b/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp index 49e7a34..cd90b25 100644 --- a/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp +++ b/src/render/backends/gl/Qt3DSRenderBackendGL3.cpp @@ -430,7 +430,6 @@ namespace render { if (inputAssembler->m_cachedShaderHandle != programID) { GL_CALL_EXTRA_FUNCTION(glBindVertexArray(inputAssembler->m_VaoID)); - inputAssembler->m_cachedShaderHandle = programID; QT3DS_FOREACH(idx, shaderAttribBuffer.size()) { @@ -454,6 +453,9 @@ namespace render { } } + // Cache the program id after checking for errors + inputAssembler->m_cachedShaderHandle = programID; + // disable max possible used first // this is currently sufficient since we always re-arrange input attributes from 0 for (QT3DSU32 i = 0; i < attribLayout->m_LayoutAttribEntries.size(); i++) { diff --git a/src/runtime/Qt3DSActivationManager.cpp b/src/runtime/Qt3DSActivationManager.cpp index 7015a61..cf14820 100644 --- a/src/runtime/Qt3DSActivationManager.cpp +++ b/src/runtime/Qt3DSActivationManager.cpp @@ -497,7 +497,12 @@ struct STimeContext void setControlled(TActivityItem &item) { - m_ControlledList.insert(item); + if (!m_ControlledList.contains(item)) { + m_ControlledList.insert(item); + qCInfo(TRACE_INFO) << "Element" << item.m_Name.c_str() + << "visibility now controlled by datainput. " + "Visibility will no longer be affected by slide transitions."; + } } static void UpdateItemScriptStatus(SElement &inNode, bool activeAndHasScript, @@ -573,9 +578,12 @@ struct STimeContext bool parentActive = theEntry.IsParentActive(); bool wasActive = theScanNode->IsGlobalActive(); + bool isControlledByDi + = controlledList.contains(*theScanNode) && theScanNode->m_OnMaster; + // Override visibility for master slide elements that have datainput eyeball controller. - bool isActive = (controlledList.contains(*theScanNode) && theScanNode->m_OnMaster) - ? theScanNode->IsControlledActive() : theScanNode->IsGlobalActive(parentActive); + bool isActive = isControlledByDi ? theScanNode->IsControlledActive() + : theScanNode->IsGlobalActive(parentActive); bool wasChildDirty = theScanNode->m_ActivationManagerNode.m_Flags.IsChildDirty(); theScanNode->m_ActivationManagerNode.m_Flags.ClearChildDirty(); bool activateChange = isActive != wasActive; @@ -583,6 +591,9 @@ struct STimeContext if (activateChange) { HandleActivationChange(*theScanNode, activateBuffer, deactivateBuffer, scriptBuffer, inElementAccessMutex, scriptBufferRequiresSort, isActive); + } else if (isControlledByDi) { + qCInfo(TRACE_INFO) << "Element" << theScanNode->m_Name.c_str() + << "visibility persistently controlled by datainput."; } if (checkChildren && theScanNode->m_Child) { @@ -590,7 +601,11 @@ struct STimeContext theScanNodeChild = theScanNodeChild->m_Sibling) { // Override visibility for master slide elements that have datainput // eyeball controller. - if (controlledList.contains(*theScanNodeChild) && theScanNodeChild->m_OnMaster) + isControlledByDi + = controlledList.contains(*theScanNodeChild) + && theScanNodeChild->m_OnMaster; + + if (isControlledByDi) theScanNodeChild->SetExplicitActive(theScanNodeChild->IsControlledActive()); if (theScanNodeChild->IsIndependent() == false) inScanBuffer.push_back(SScanBufferEntry(theScanNodeChild, isActive)); @@ -649,7 +664,12 @@ struct STimeContext parentActive = theParent->IsGlobalActive(); bool wasActive = theContextNode.IsGlobalActive(); - bool isActive = theContextNode.IsGlobalActive(parentActive); + bool isControlledByDi + = m_ControlledList.contains(theContextNode) && theContextNode.m_OnMaster; + + // Override visibility for master slide elements that have datainput eyeball controller. + bool isActive = isControlledByDi ? theContextNode.IsControlledActive() + : theContextNode.IsGlobalActive(parentActive); bool activationChange = isActive != wasActive; inPerfTimer.Update("ActivationManager - Update Initial Vars", qt3ds::foundation::Time::getCurrentCounterValue() - start); diff --git a/src/runtime/Qt3DSApplication.cpp b/src/runtime/Qt3DSApplication.cpp index abe93c8..13fe7a9 100644 --- a/src/runtime/Qt3DSApplication.cpp +++ b/src/runtime/Qt3DSApplication.cpp @@ -114,8 +114,10 @@ bool qt3ds::runtime::isImagePath(const QString &path) const QString ext = path.right(path.length() - index - 1); return (ext == QLatin1String("jpg") || ext == QLatin1String("jpeg") || ext == QLatin1String("png") || ext == QLatin1String("hdr") - || ext == QLatin1String("dds") || ext == QLatin1String("ktx") - || ext == QLatin1String("astc")); +#ifndef LEGACY_ASTC_LOADING + || ext == QLatin1String("astc") +#endif + || ext == QLatin1String("dds") || ext == QLatin1String("ktx")); } struct SFrameTimer @@ -221,13 +223,6 @@ struct SHandleElementPairComparator static int s_debug = -1; -static bool debuggingEnabled() -{ - if (s_debug == -1) - s_debug = qEnvironmentVariableIntValue("QT3DS_DEBUG"); - return s_debug >= 1; -} - struct SSlideResourceCounter { QHash<QString, int> counters; @@ -295,20 +290,20 @@ struct SSlideResourceCounter } void print() { - if (debuggingEnabled()) { - qDebug() << "SlideResourceCounter resources:"; + if (qt3ds::TRACE_INFO().isInfoEnabled()) { + qCInfo(qt3ds::TRACE_INFO) << "SlideResourceCounter resources:"; const auto keys = counters.keys(); for (auto &x : keys) - qDebug() << x << ": " << counters[x]; + qCInfo(qt3ds::TRACE_INFO) << x << ": " << counters[x]; if (createSet.size()) { - qDebug() << "New resources: "; + qCInfo(qt3ds::TRACE_INFO) << "New resources: "; for (auto y : qAsConst(createSet)) - qDebug() << y; + qCInfo(qt3ds::TRACE_INFO) << y; } if (deleteSet.size()) { - qDebug() << "Deleted resources: "; + qCInfo(qt3ds::TRACE_INFO) << "Deleted resources: "; for (auto y : qAsConst(deleteSet)) - qDebug() << y; + qCInfo(qt3ds::TRACE_INFO) << y; } } } @@ -1220,7 +1215,7 @@ struct SApp : public IApplication slidesystem.setUnloadSlide(key, false); const QString completeName = presentation->GetName() + QLatin1Char(':') + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName; - qCInfo(PERF_INFO) << "Load component slide resources: " << completeName; + qCInfo(TRACE_INFO) << "Load component slide resources: " << completeName; m_resourceCounter.handleLoadSlide(completeName, key, slidesystem); if (m_uploadRenderTask) m_uploadRenderTask->add(m_resourceCounter.createSet, wait); @@ -1231,7 +1226,7 @@ struct SApp : public IApplication getComponentSlideAssets(newAssets, presentation, component, index); if (newAssets.size()) - qCInfo(PERF_INFO) << "Slide assets: " << newAssets; + qCInfo(TRACE_INFO) << "Slide assets: " << newAssets; for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) { QString assetId = QString::fromUtf8(m_OrderedAssets[idx].first.c_str()); if (newAssets.contains(assetId) && !GetPresentationById(qUtf8Printable(assetId))) { @@ -1292,7 +1287,7 @@ struct SApp : public IApplication if (!slidesystem.isActiveSlide(key)) { const QString completeName = presentation->GetName() + QLatin1Char(':') + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName; - qCInfo(PERF_INFO) << "Unload component slide resources: " << completeName; + qCInfo(TRACE_INFO) << "Unload component slide resources: " << completeName; m_resourceCounter.handleUnloadSlide(completeName, key, slidesystem); if (m_uploadRenderTask) diff --git a/src/runtime/Qt3DSIScriptBridge.h b/src/runtime/Qt3DSIScriptBridge.h index b9df2b3..f424aac 100644 --- a/src/runtime/Qt3DSIScriptBridge.h +++ b/src/runtime/Qt3DSIScriptBridge.h @@ -187,6 +187,8 @@ public: // Elements qt3ds::render::IBufferManager *bufferManager) = 0; virtual void deleteMeshes(const QStringList &elementPath, qt3ds::render::IBufferManager *bufferManager) = 0; + virtual uint textureId(const QString &elementPath, + qt3ds::render::IQt3DSRenderer *renderer) = 0; public: // Components virtual void GotoSlide(const char *component, const char *slideName, diff --git a/src/runtime/Qt3DSQmlEngine.cpp b/src/runtime/Qt3DSQmlEngine.cpp index 0bfddba..c7e6e88 100644 --- a/src/runtime/Qt3DSQmlEngine.cpp +++ b/src/runtime/Qt3DSQmlEngine.cpp @@ -450,6 +450,8 @@ public: qt3ds::render::IBufferManager *bufferManager) override; void deleteMeshes(const QStringList &meshNames, qt3ds::render::IBufferManager *bufferManager) override; + uint textureId(const QString &elementPath, + qt3ds::render::IQt3DSRenderer *renderer) override; void GotoSlide(const char *component, const char *slideName, const SScriptEngineGotoSlideArgs &inArgs) override; @@ -1833,6 +1835,27 @@ void CQmlEngineImpl::deleteMeshes(const QStringList &meshNames, } } +uint CQmlEngineImpl::textureId(const QString &elementPath, + qt3ds::render::IQt3DSRenderer *renderer) +{ + TElement *elem = getTarget(elementPath.toUtf8().constData()); + if (elem) { + auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(elem->GetAssociation()); + if (translator) { + qt3ds::render::GraphObjectTypes::Enum type = translator->GetUIPType(); + if (type == qt3ds::render::GraphObjectTypes::Layer) { + auto layer = static_cast<qt3ds::render::SLayer *>(&translator->RenderObject()); + return renderer->getLayerTextureId(*layer); + } else if (type == qt3ds::render::GraphObjectTypes::Image) { + auto image = static_cast<qt3ds::render::SImage *>(&translator->RenderObject()); + return static_cast<uint>(reinterpret_cast<size_t>( + image->m_TextureData.m_Texture->GetTextureObjectHandle())); + } + } + } + return 0; +} + void CQmlEngineImpl::GotoSlide(const char *component, const char *slideName, const SScriptEngineGotoSlideArgs &inArgs) { diff --git a/src/runtime/q3dsmaterialdefinitionparser.cpp b/src/runtime/q3dsmaterialdefinitionparser.cpp index 913a24e..1cdbc48 100644 --- a/src/runtime/q3dsmaterialdefinitionparser.cpp +++ b/src/runtime/q3dsmaterialdefinitionparser.cpp @@ -52,6 +52,7 @@ void Q3DSMaterialDefinitionParser::getMaterialInfo(const QString &materialDefini return; } QTextStream stream(&file); + stream.setCodec("UTF-8"); matDef = stream.readAll(); } else { matDef = materialDefinition; diff --git a/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp b/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp index b919ca5..d19c9f6 100644 --- a/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp +++ b/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp @@ -494,7 +494,8 @@ bool Q3DSDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font) resizeTexture(texInfo, width, height); - memcpy(texInfo->copy.bits(), textureData, size); + for (int y = 0; y < height; ++y) + memcpy(texInfo->copy.scanLine(y), textureData + y * width, width); textureData += size; QImage &image = texInfo->copy; diff --git a/src/runtimerender/Qt3DSRenderContextCore.h b/src/runtimerender/Qt3DSRenderContextCore.h index dab5be9..9a26876 100644 --- a/src/runtimerender/Qt3DSRenderContextCore.h +++ b/src/runtimerender/Qt3DSRenderContextCore.h @@ -57,7 +57,9 @@ namespace render { enum Enum { Mono, TopBottom, - LeftRight + LeftRight, + AnaglyphRedCyan, + AnaglyphGreenMagenta }; }; diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialRenderContext.h b/src/runtimerender/Qt3DSRenderCustomMaterialRenderContext.h index 5283660..06267d2 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialRenderContext.h +++ b/src/runtimerender/Qt3DSRenderCustomMaterialRenderContext.h @@ -56,7 +56,7 @@ namespace render { const QT3DSMat44 &m_ModelViewProjection; const QT3DSMat44 &m_ModelMatrix; ///< model to world transformation const QT3DSMat33 &m_NormalMatrix; - const SCustomMaterial &m_Material; + SCustomMaterial &m_Material; const NVRenderTexture2D *m_DepthTexture; const NVRenderTexture2D *m_AOTexture; SShaderDefaultMaterialKey m_MaterialKey; @@ -66,7 +66,7 @@ namespace render { SCustomMaterialRenderContext( const SLayer &layer, const SLayerRenderData &data, NVDataRef<SLight *> lights, const SCamera &cam, const SModel &m, const SRenderSubset &subset, const QT3DSMat44 &mvp, - const QT3DSMat44 &world, const QT3DSMat33 &nm, const SCustomMaterial &material, + const QT3DSMat44 &world, const QT3DSMat33 &nm, SCustomMaterial &material, const NVRenderTexture2D *depthTex, const NVRenderTexture2D *aoTex, SShaderDefaultMaterialKey inMaterialKey, SRenderableImage *inFirstImage = NULL, QT3DSF32 opacity = 1.0) diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp index 1b0b304..82a4d73 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp +++ b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp @@ -1200,7 +1200,8 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator } NVRenderShaderProgram *GenerateCustomMaterialShader(const char8_t *inShaderPrefix, - const char8_t *inCustomMaterialName) + const char8_t *inCustomMaterialName, + QString &errors) { // build a string that allows us to print out the shader we are generating to the log. // This is time consuming but I feel like it doesn't happen all that often and is very @@ -1231,7 +1232,8 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator VertexGenerator().EndFragmentGeneration(hasCustomFragmentShader); NVRenderShaderProgram *program = ProgramGenerator().CompileGeneratedShader( - m_GeneratedShaderString.c_str(), SShaderCacheProgramFlags(), FeatureSet()); + m_GeneratedShaderString.c_str(), SShaderCacheProgramFlags(), FeatureSet(), + errors); if (program && hasCustomVertexShader) { // Change uniforms names to match runtime 2.x uniforms SShaderGeneratorGeneratedShader &shader(GetShaderForProgram(*program)); @@ -1255,7 +1257,7 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, - bool inHasTransparency, const char8_t *inShaderPrefix, + bool inHasTransparency, const char8_t *inShaderPrefix, QString &error, const char8_t *inCustomMaterialName) override { QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::CustomMaterial); @@ -1267,7 +1269,21 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator m_FirstImage = inFirstImage; m_HasTransparency = inHasTransparency; - return GenerateCustomMaterialShader(inShaderPrefix, inCustomMaterialName); + return GenerateCustomMaterialShader(inShaderPrefix, inCustomMaterialName, error); + } + + virtual NVRenderShaderProgram * + GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, + IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, + NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, + bool inHasTransparency, const char8_t *inShaderPrefix, + const char8_t *inCustomMaterialName) override + { + QString error; + + return GenerateShader(inMaterial, inShaderDescription, inVertexPipeline, inFeatureSet, + inLights, inFirstImage, inHasTransparency, inShaderPrefix, + error, inCustomMaterialName); } }; } diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h index 29c31ff..7a3cfad 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h +++ b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.h @@ -50,7 +50,15 @@ namespace render { const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, - const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override = 0; + const char8_t *inVertexPipelineName, QString &error, + const char8_t *inCustomMaterialName = "") override = 0; + + NVRenderShaderProgram *GenerateShader( + const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, + IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, + NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, + const char8_t *inVertexPipelineName, + const char8_t *inCustomMaterialName = "") override = 0; // Also sets the blend function on the render context. virtual void diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp index 62d9805..b40e10e 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp +++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp @@ -1208,7 +1208,8 @@ struct SMaterialSystem : public ICustomMaterialSystem NVRenderShaderProgram *GetShader(SCustomMaterialRenderContext &inRenderContext, const SCustomMaterial &inMaterial, const SBindShader &inCommand, TShaderFeatureSet inFeatureSet, - const dynamic::SDynamicShaderProgramFlags &inFlags) + const dynamic::SDynamicShaderProgramFlags &inFlags, + QString &errors) { ICustomMaterialShaderGenerator &theMaterialGenerator( m_Context->GetCustomMaterialShaderGenerator()); @@ -1225,7 +1226,7 @@ struct SMaterialSystem : public ICustomMaterialSystem inMaterial, inRenderContext.m_MaterialKey, thePipeline, inFeatureSet, inRenderContext.m_Lights, inRenderContext.m_FirstImage, (inMaterial.m_hasTransparency || inMaterial.m_hasRefraction), - "custom material pipeline-- ", inCommand.m_ShaderPath.c_str()); + "custom material pipeline-- ", errors, inCommand.m_ShaderPath.c_str()); return theProgram; } @@ -1233,7 +1234,8 @@ struct SMaterialSystem : public ICustomMaterialSystem SMaterialOrComputeShader BindShader(SCustomMaterialRenderContext &inRenderContext, const SCustomMaterial &inMaterial, const SBindShader &inCommand, - TShaderFeatureSet inFeatureSet) + TShaderFeatureSet inFeatureSet, + QString &errors) { NVRenderShaderProgram *theProgram = NULL; eastl::vector<SShaderPreprocessorFeature> features; @@ -1256,7 +1258,8 @@ struct SMaterialSystem : public ICustomMaterialSystem eastl::make_pair(skey, NVScopedRefCounted<SCustomMaterialShader>(NULL)))); if (theInsertResult.second || requiresCompilation(inMaterial.m_ClassName)) { - theProgram = GetShader(inRenderContext, inMaterial, inCommand, featureSet, theFlags); + theProgram = GetShader(inRenderContext, inMaterial, inCommand, featureSet, theFlags, + errors); if (theProgram) { theInsertResult.first->second = @@ -1264,7 +1267,6 @@ struct SMaterialSystem : public ICustomMaterialSystem } } else if (theInsertResult.first->second) theProgram = theInsertResult.first->second->m_Shader; - setRequiresCompilation(inMaterial.m_ClassName, false); if (theProgram) { @@ -1741,7 +1743,7 @@ struct SMaterialSystem : public ICustomMaterialSystem } void DoRenderCustomMaterial(SCustomMaterialRenderContext &inRenderContext, - const SCustomMaterial &inMaterial, SMaterialClass &inClass, + SCustomMaterial &inMaterial, SMaterialClass &inClass, NVRenderFrameBuffer *inTarget, TShaderFeatureSet inFeatureSet) { NVRenderContext &theContext = m_Context->GetRenderContext(); @@ -1766,6 +1768,7 @@ struct SMaterialSystem : public ICustomMaterialSystem bool theRenderTargetNeedsClear = false; NVConstDataRef<dynamic::SCommand *> theCommands(inClass.m_Class->GetRenderCommands()); + QString errors; for (QT3DSU32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd; ++commandIdx) { const SCommand &theCommand(*theCommands[commandIdx]); @@ -1788,9 +1791,11 @@ struct SMaterialSystem : public ICustomMaterialSystem theCurrentShader = NULL; SMaterialOrComputeShader theBindResult = BindShader(inRenderContext, inMaterial, - static_cast<const SBindShader &>(theCommand), inFeatureSet); + static_cast<const SBindShader &>(theCommand), inFeatureSet, errors); if (theBindResult.IsMaterialShader()) theCurrentShader = &theBindResult.MaterialShader(); + if (!errors.isEmpty()) + inMaterial.SetError(m_CoreContext.GetStringTable().RegisterStr(errors)); } break; case CommandTypes::ApplyInstanceValue: // we apply the property update explicitly at the render pass @@ -2135,6 +2140,11 @@ struct SMaterialSystem : public ICustomMaterialSystem m_LastFrameTime = currentFrameTime; } + IQt3DSRenderContext *getContext() override + { + return m_Context; + } + void Save(qt3ds::render::SWriteBuffer &ioBuffer, const qt3ds::render::SStrRemapMap &inRemapMap, const char8_t * /*inProjectDir*/) const override diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h index 6bf422c..0f87533 100644 --- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h +++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h @@ -133,6 +133,7 @@ namespace render { virtual bool requiresCompilation(const CRegisteredString &name) const = 0; // Called by the uiccontext so this system can clear any per-frame render information. virtual void EndFrame() = 0; + virtual IQt3DSRenderContext *getContext() = 0; }; struct QT3DS_AUTOTEST_EXPORT SCustomMaterialVertexPipeline : public SVertexPipelineImpl diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp index 4a1f6e3..0789d51 100644 --- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp +++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp @@ -1877,8 +1877,23 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, - bool inHasTransparency, const char8_t *inVertexPipelineName, const char8_t *) override + bool inHasTransparency, const char8_t *inVertexPipelineName, + const char8_t *) override { + QString error; + return GenerateShader(inMaterial, inShaderDescription, inVertexPipeline, inFeatureSet, + inLights, inFirstImage, inHasTransparency, inVertexPipelineName, + error, ""); + } + + virtual NVRenderShaderProgram * + GenerateShader(const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, + IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, + NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, + bool inHasTransparency, const char8_t *inVertexPipelineName, QString &error, + const char8_t *) override + { + Q_UNUSED(error) QT3DS_ASSERT(inMaterial.m_Type == GraphObjectTypes::DefaultMaterial); m_CurrentMaterial = static_cast<const SDefaultMaterial *>(&inMaterial); m_CurrentKey = &inShaderDescription; diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h index 871ab1b..4d82f4c 100644 --- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h +++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.h @@ -101,7 +101,15 @@ namespace render { const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, - const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") override = 0; + const char8_t *inVertexPipelineName, QString &error, + const char8_t *inCustomMaterialName = "") override = 0; + + NVRenderShaderProgram *GenerateShader( + const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, + IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, + NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, + const char8_t *inVertexPipelineName, + const char8_t *inCustomMaterialName = "") override = 0; // generate default material shader for depth only pass virtual NVRenderShaderProgram *GenerateDepthPassShader( diff --git a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp index b3395f3..cb629cc 100644 --- a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp +++ b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp @@ -1325,6 +1325,7 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem CRegisteredString inProgramMacroName, TShaderFeatureSet inFeatureSet, const dynamic::SDynamicShaderProgramFlags &inFlags, + QString &errors, bool inForceCompilation = false) { m_VertShader.clear(); @@ -1385,11 +1386,11 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem return theShaderCache.ForceCompileProgram(theKey, m_VertShader.c_str(), m_FragShader.c_str(), NULL, NULL, m_GeometryShader.c_str(), theFlags, - inFeatureSet, false); + inFeatureSet, errors, false); } return theShaderCache.CompileProgram(theKey, m_VertShader.c_str(), m_FragShader.c_str(), NULL, NULL, m_GeometryShader.c_str(), theFlags, - inFeatureSet); + inFeatureSet, errors); } // This just returns the custom material shader source without compiling @@ -1406,7 +1407,7 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem CRegisteredString inProgramMacro, TShaderFeatureSet inFeatureSet, const SDynamicShaderProgramFlags &inFlags, - bool inForceCompilation) override + QString &errors, bool inForceCompilation) override { eastl::pair<const SShaderMapKey, TShaderAndFlags> theInserter( SShaderMapKey(TStrStrPair(inPath, inProgramMacro), inFeatureSet, inFlags.m_TessMode, @@ -1426,8 +1427,9 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem DoLoadShader(inPath, theShaderBuffer); if (theShaderInfo.m_HasGeomShader) theFlags.SetGeometryShaderEnabled(true); - theProgram = CompileShader(inPath, theShaderBuffer.c_str(), NULL, inProgramMacro, - inFeatureSet, theFlags, inForceCompilation); + theProgram = CompileShader( + inPath, theShaderBuffer.c_str(), NULL, inProgramMacro, + inFeatureSet, theFlags, errors, inForceCompilation); } else { Qt3DSString theShaderBuffer; const char8_t *shaderVersionStr = "#version 430\n"; @@ -1505,8 +1507,9 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem programBuffer.append(fragmentSource); programBuffer.append("\n#endif"); flags.SetGeometryShaderEnabled(true); + QString error; theProgram = CompileShader(inPath, programBuffer.c_str(), theShaderBuffer.c_str(), - theProgramMacro, inFeatureSet, flags); + theProgramMacro, inFeatureSet, flags, error); } theInsertResult.first->second = TShaderAndFlags(theProgram, flags); } diff --git a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h index cfe022e..5379df2 100644 --- a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h +++ b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h @@ -265,7 +265,7 @@ namespace render { GetShaderProgram(CRegisteredString inPath, CRegisteredString inProgramMacro, TShaderFeatureSet inFeatureSet, const dynamic::SDynamicShaderProgramFlags &inFlags, - bool inForceCompilation = false) = 0; + QString &errors, bool inForceCompilation = false) = 0; virtual void GetShaderSource(CRegisteredString inPath, Qt3DSString &outSource) = 0; diff --git a/src/runtimerender/Qt3DSRenderEffectSystem.cpp b/src/runtimerender/Qt3DSRenderEffectSystem.cpp index 81027f1..2db30bb 100644 --- a/src/runtimerender/Qt3DSRenderEffectSystem.cpp +++ b/src/runtimerender/Qt3DSRenderEffectSystem.cpp @@ -1020,7 +1020,8 @@ struct SEffectSystem : public IEffectSystem return theBuffer; } - SEffectShader *BindShader(CRegisteredString &inEffectId, const SBindShader &inCommand) + SEffectShader *BindShader(CRegisteredString &inEffectId, const SBindShader &inCommand, + QString &errors) { SEffectClass *theClass = GetEffectClass(inEffectId); if (!theClass) { @@ -1039,7 +1040,7 @@ struct SEffectSystem : public IEffectSystem NVRenderShaderProgram *theProgram = m_Context->GetDynamicObjectSystem() .GetShaderProgram(inCommand.m_ShaderPath, inCommand.m_ShaderDefine, - TShaderFeatureSet(), SDynamicShaderProgramFlags(), + TShaderFeatureSet(), SDynamicShaderProgramFlags(), errors, forceCompilation).first; if (theProgram) theInsertResult.first->second = QT3DS_NEW(m_Allocator, SEffectShader)(*theProgram); @@ -1546,6 +1547,7 @@ struct SEffectSystem : public IEffectSystem theContext.SetDepthWriteEnabled(false); QT3DSMat44 theMVP(QT3DSMat44::createIdentity()); + QString errors; NVConstDataRef<dynamic::SCommand *> theCommands = inClass.m_DynamicClass->GetRenderCommands(); for (QT3DSU32 commandIdx = 0, commandEnd = theCommands.size(); commandIdx < commandEnd; @@ -1592,7 +1594,10 @@ struct SEffectSystem : public IEffectSystem } break; case CommandTypes::BindShader: theCurrentShader = BindShader(inEffect.m_ClassName, - static_cast<const SBindShader &>(theCommand)); + static_cast<const SBindShader &>(theCommand), + errors); + if (!errors.isEmpty()) + inEffect.SetError(m_CoreContext.GetStringTable().RegisterStr(errors)); break; case CommandTypes::ApplyInstanceValue: if (theCurrentShader) @@ -1719,13 +1724,18 @@ struct SEffectSystem : public IEffectSystem QT3DSU32 theFinalWidth = ITextRenderer::NextMultipleOf4((QT3DSU32)(theDetails.m_Width)); QT3DSU32 theFinalHeight = ITextRenderer::NextMultipleOf4((QT3DSU32)(theDetails.m_Height)); NVRenderFrameBuffer *theBuffer = theManager.AllocateFrameBuffer(); - // UdoL Some Effects may need to run before HDR tonemap. This means we need to keep the - // input format - NVRenderTextureFormats::Enum theOutputFormat = NVRenderTextureFormats::RGBA8; - if (theClass->m_DynamicClass->GetOutputTextureFormat() == NVRenderTextureFormats::Unknown) - theOutputFormat = theDetails.m_Format; - NVRenderTexture2D *theTargetTexture = - theManager.AllocateTexture2D(theFinalWidth, theFinalHeight, theOutputFormat); + NVRenderTexture2D *theTargetTexture = inRenderArgument.m_targetTexture; + if (theTargetTexture == nullptr) { + // Some Effects may need to run before HDR tonemap. This means we need to keep the + // input format + NVRenderTextureFormats::Enum theOutputFormat = NVRenderTextureFormats::RGBA8; + if (theClass->m_DynamicClass->GetOutputTextureFormat() + == NVRenderTextureFormats::Unknown) { + theOutputFormat = theDetails.m_Format; + } + theTargetTexture = theManager.AllocateTexture2D(theFinalWidth, theFinalHeight, + theOutputFormat); + } theBuffer->Attach(NVRenderFrameBufferAttachments::Color0, *theTargetTexture); theContext.SetRenderTarget(theBuffer); NVRenderContextScopedProperty<NVRenderRect> __viewport( diff --git a/src/runtimerender/Qt3DSRenderEffectSystem.h b/src/runtimerender/Qt3DSRenderEffectSystem.h index a9ea7c5..def1539 100644 --- a/src/runtimerender/Qt3DSRenderEffectSystem.h +++ b/src/runtimerender/Qt3DSRenderEffectSystem.h @@ -57,16 +57,19 @@ namespace render { // this is a depth preapass texture we need for some effects like bloom // actually we need the stencil values NVRenderTexture2D *m_DepthStencilBuffer; + NVRenderTexture2D *m_targetTexture; SEffectRenderArgument(SEffect &inEffect, NVRenderTexture2D &inColorBuffer, const QT3DSVec2 &inCameraClipRange, - NVRenderTexture2D *inDepthTexture = NULL, - NVRenderTexture2D *inDepthBuffer = NULL) + NVRenderTexture2D *inDepthTexture = nullptr, + NVRenderTexture2D *inDepthBuffer = nullptr, + NVRenderTexture2D *targetTexture = nullptr) : m_Effect(inEffect) , m_ColorBuffer(inColorBuffer) , m_CameraClipRange(inCameraClipRange) , m_DepthTexture(inDepthTexture) , m_DepthStencilBuffer(inDepthBuffer) + , m_targetTexture(targetTexture) { } }; diff --git a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h index 88858bd..5d70931 100644 --- a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h +++ b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h @@ -136,6 +136,13 @@ namespace render { const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, + const char8_t *inVertexPipelineName, QString &error, + const char8_t *inCustomMaterialName = "") = 0; + + virtual NVRenderShaderProgram *GenerateShader( + const SGraphObject &inMaterial, SShaderDefaultMaterialKey inShaderDescription, + IShaderStageGenerator &inVertexPipeline, TShaderFeatureSet inFeatureSet, + NVDataRef<SLight *> inLights, SRenderableImage *inFirstImage, bool inHasTransparency, const char8_t *inVertexPipelineName, const char8_t *inCustomMaterialName = "") = 0; // Also sets the blend function on the render context. diff --git a/src/runtimerender/Qt3DSRenderShaderCache.cpp b/src/runtimerender/Qt3DSRenderShaderCache.cpp index c642360..21d2247 100644 --- a/src/runtimerender/Qt3DSRenderShaderCache.cpp +++ b/src/runtimerender/Qt3DSRenderShaderCache.cpp @@ -383,7 +383,7 @@ struct ShaderCache : public IShaderCache const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom, const SShaderCacheProgramFlags &inFlags, NVConstDataRef<SShaderPreprocessorFeature> inFeatures, - bool separableProgram, bool fromDisk = false) override + QString &errors, bool separableProgram, bool fromDisk = false) override { if (m_ShaderCompilationEnabled == false) return nullptr; @@ -421,14 +421,15 @@ struct ShaderCache : public IShaderCache if (!fromDisk) addShaderPreprocessors(inKey, inFlags, inFeatures, separableProgram, false); - theInserter.first->second = - m_RenderContext + NVRenderVertFragCompilationResult res = m_RenderContext .CompileSource(inKey, m_VertexCode.c_str(), QT3DSU32(m_VertexCode.size()), m_FragmentCode.c_str(), QT3DSU32(m_FragmentCode.size()), m_TessCtrlCode.c_str(), QT3DSU32(m_TessCtrlCode.size()), m_TessEvalCode.c_str(), QT3DSU32(m_TessEvalCode.size()), m_GeometryCode.c_str(), QT3DSU32(m_GeometryCode.size()), - separableProgram).mShader; + separableProgram); + theInserter.first->second = res.mShader; + errors = res.errors; // This is unnecessary memory waste in final deployed product, so we don't store this // information when shaders were initialized from a cache. @@ -456,7 +457,8 @@ struct ShaderCache : public IShaderCache CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag, const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom, const SShaderCacheProgramFlags &inFlags, - NVConstDataRef<SShaderPreprocessorFeature> inFeatures, bool separableProgram) override + NVConstDataRef<SShaderPreprocessorFeature> inFeatures, + QString &errors, bool separableProgram) override { NVRenderShaderProgram *theProgram = GetProgram(inKey, inFeatures); if (theProgram) @@ -464,7 +466,7 @@ struct ShaderCache : public IShaderCache NVRenderShaderProgram *retval = ForceCompileProgram(inKey, inVert, inFrag, inTessCtrl, inTessEval, inGeom, inFlags, - inFeatures, separableProgram); + inFeatures, errors, separableProgram); return retval; } @@ -622,6 +624,7 @@ struct ShaderCache : public IShaderCache if (!loadVertexData.isEmpty() && (!loadFragmentData.isEmpty() || !loadGeometryData.isEmpty())) { + QString error; theShader = ForceCompileProgram( theKey, loadVertexData.constData(), loadFragmentData.constData(), @@ -631,7 +634,7 @@ struct ShaderCache : public IShaderCache SShaderCacheProgramFlags(), qt3ds::foundation::toDataRef( features.data(), static_cast<QT3DSU32>(features.size())), - false, true); + error, false, true); } } // If something doesn't save or load correctly, get the runtime to re-generate. diff --git a/src/runtimerender/Qt3DSRenderShaderCache.h b/src/runtimerender/Qt3DSRenderShaderCache.h index ca333c6..d03bc65 100644 --- a/src/runtimerender/Qt3DSRenderShaderCache.h +++ b/src/runtimerender/Qt3DSRenderShaderCache.h @@ -123,7 +123,7 @@ namespace render { ForceCompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag, const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom, const SShaderCacheProgramFlags &inFlags, - TShaderFeatureSet inFeatures, bool separableProgram, + TShaderFeatureSet inFeatures, QString &errors, bool separableProgram, bool fromDisk = false) = 0; // It is up to the caller to ensure that inFeatures contains unique keys. @@ -132,7 +132,18 @@ namespace render { CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag, const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom, const SShaderCacheProgramFlags &inFlags, TShaderFeatureSet inFeatures, - bool separableProgram = false) = 0; + QString &errors, bool separableProgram = false) = 0; + + virtual NVRenderShaderProgram * + CompileProgram(CRegisteredString inKey, const char8_t *inVert, const char8_t *inFrag, + const char8_t *inTessCtrl, const char8_t *inTessEval, const char8_t *inGeom, + const SShaderCacheProgramFlags &inFlags, TShaderFeatureSet inFeatures, + bool separableProgram = false) + { + QString errors; + return CompileProgram(inKey, inVert, inFrag, inTessCtrl, inTessEval, inGeom, inFlags, + inFeatures, errors, separableProgram); + } // Used to disable any shader compilation during loading. This is used when we are just // interested in going from uia->binary diff --git a/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.cpp b/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.cpp index cfdf47a..74af857 100644 --- a/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.cpp +++ b/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.cpp @@ -511,6 +511,16 @@ struct SProgramGenerator : public IShaderProgramGenerator CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags, TShaderFeatureSet inFeatureSet, bool separableProgram) override { + QString errors; + return CompileGeneratedShader(inShaderName, inFlags, inFeatureSet, errors, + separableProgram); + } + + qt3ds::render::NVRenderShaderProgram * + CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags, + TShaderFeatureSet inFeatureSet, QString &errors, + bool separableProgram) override + { // No stages enabled if (((QT3DSU32)m_EnabledStages) == 0) { QT3DS_ASSERT(false); @@ -542,7 +552,7 @@ struct SProgramGenerator : public IShaderProgramGenerator CRegisteredString theCacheKey = m_Context.GetStringTable().RegisterStr(inShaderName); return theCache.CompileProgram(theCacheKey, vertexShaderSource, fragmentShaderSource, tcShaderSource, teShaderSource, geShaderSource, - theCacheFlags, inFeatureSet, separableProgram); + theCacheFlags, inFeatureSet, errors, separableProgram); } }; }; diff --git a/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.h b/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.h index 6a6e967..676f00b 100644 --- a/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.h +++ b/src/runtimerender/Qt3DSRenderShaderCodeGeneratorV2.h @@ -115,11 +115,26 @@ namespace render { CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags, TShaderFeatureSet inFeatureSet, bool separableProgram = false) = 0; + virtual qt3ds::render::NVRenderShaderProgram * + CompileGeneratedShader(const char *inShaderName, const SShaderCacheProgramFlags &inFlags, + TShaderFeatureSet inFeatureSet, QString &errors, + bool separableProgram = false) = 0; + + + qt3ds::render::NVRenderShaderProgram *CompileGeneratedShader(const char *inShaderName, + bool separableProgram = false) + { + QString errors; + return CompileGeneratedShader(inShaderName, SShaderCacheProgramFlags(), + TShaderFeatureSet(), errors, separableProgram); + } + qt3ds::render::NVRenderShaderProgram *CompileGeneratedShader(const char *inShaderName, - bool separableProgram = false) + QString &errors, + bool separableProgram = false) { return CompileGeneratedShader(inShaderName, SShaderCacheProgramFlags(), - TShaderFeatureSet(), separableProgram); + TShaderFeatureSet(), errors, separableProgram); } static IShaderProgramGenerator &CreateProgramGenerator(IQt3DSRenderContext &inContext); diff --git a/src/runtimerender/Qt3DSRenderer.h b/src/runtimerender/Qt3DSRenderer.h index fb6c3de..392fb62 100644 --- a/src/runtimerender/Qt3DSRenderer.h +++ b/src/runtimerender/Qt3DSRenderer.h @@ -167,6 +167,8 @@ namespace render { const QT3DSVec3 &inMouseVec) const = 0; virtual QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const = 0; + virtual uint getLayerTextureId(SLayer &layer) = 0; + // Roughly equivalent of gluPickMatrix, allows users to setup a perspective transform that // will draw some sub component // of the layer. Used in combination with an expected viewport of 0,0,width,height the diff --git a/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h b/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h index 1202c7c..7c6b10e 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h +++ b/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h @@ -86,6 +86,8 @@ namespace render { SCustomMaterialShaderKeyFlags m_ShaderKeyValues; ///< input from MDL files QT3DSU32 m_LayerCount; ///< input from MDL files + CRegisteredString m_error; // shader compile error + void Initialize(QT3DSU32 inKey, QT3DSU32 inLayerCount) { m_Lightmaps.m_LightmapIndirect = NULL; @@ -103,6 +105,7 @@ namespace render { m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)inKey; m_LayerCount = inLayerCount; m_imageMaps = nullptr; + m_error = CRegisteredString(); } bool IsDielectric() const @@ -127,6 +130,16 @@ namespace render { } bool HasLighting() const { return true; } + CRegisteredString GetError() const + { + return m_error; + } + + void SetError(const CRegisteredString &error) + { + m_error = error; + } + template <typename TRemapperType> void Remap(TRemapperType &inRemapper) { diff --git a/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp b/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp index d22c3c3..279946a 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp +++ b/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp @@ -42,6 +42,7 @@ void SEffect::Initialize() m_NextEffect = NULL; m_Context = NULL; m_imageMaps = nullptr; + m_error = CRegisteredString(); } void SEffect::SetActive(bool inActive, IEffectSystem &inManager) @@ -60,3 +61,13 @@ void SEffect::Reset(IEffectSystem &inSystem) inSystem.ResetEffectFrameData(*m_Context); m_Flags.SetDirty(true); } + +CRegisteredString SEffect::GetError() const +{ + return m_error; +} + +void SEffect::SetError(const CRegisteredString &error) +{ + m_error = error; +} diff --git a/src/runtimerender/graphobjects/Qt3DSRenderEffect.h b/src/runtimerender/graphobjects/Qt3DSRenderEffect.h index 1ffc95f..e0db3d9 100644 --- a/src/runtimerender/graphobjects/Qt3DSRenderEffect.h +++ b/src/runtimerender/graphobjects/Qt3DSRenderEffect.h @@ -66,6 +66,8 @@ namespace render { typedef qt3ds::foundation::nvhash_map<CRegisteredString, SImage *> TImageMapHash; TImageMapHash *m_imageMaps; + CRegisteredString m_error; + void Initialize(); // If our active flag value changes, then we ask the effect manager @@ -74,6 +76,9 @@ namespace render { void Reset(IEffectSystem &inSystem); + CRegisteredString GetError() const; + void SetError(const CRegisteredString &error); + // Generic method used during serialization // to remap string and object pointers template <typename TRemapperType> diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h index 6dbc624..abc8143 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h +++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h @@ -296,14 +296,14 @@ namespace render { */ struct SSubsetRenderable : public SSubsetRenderableBase { - const SDefaultMaterial &m_Material; + SDefaultMaterial &m_Material; SRenderableImage *m_FirstImage; SShaderDefaultMaterialKey m_ShaderDescription; NVConstDataRef<QT3DSMat44> m_Bones; SSubsetRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt, Qt3DSRendererImpl &gen, const SRenderSubset &subset, - const SDefaultMaterial &mat, const SModelContext &modelContext, + SDefaultMaterial &mat, const SModelContext &modelContext, QT3DSF32 inOpacity, SRenderableImage *inFirstImage, SShaderDefaultMaterialKey inShaderKey, NVConstDataRef<QT3DSMat44> inBoneGlobals) @@ -334,13 +334,13 @@ namespace render { struct SCustomMaterialRenderable : public SSubsetRenderableBase { - const SCustomMaterial &m_Material; + SCustomMaterial &m_Material; SRenderableImage *m_FirstImage; SShaderDefaultMaterialKey m_ShaderDescription; SCustomMaterialRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt, Qt3DSRendererImpl &gen, const SRenderSubset &subset, - const SCustomMaterial &mat, const SModelContext &modelContext, + SCustomMaterial &mat, const SModelContext &modelContext, QT3DSF32 inOpacity, SRenderableImage *inFirstImage, SShaderDefaultMaterialKey inShaderKey) : SSubsetRenderableBase(inFlags, inWorldCenterPt, gen, subset, modelContext, inOpacity) @@ -451,8 +451,8 @@ namespace render { SPathRenderable(SRenderableObjectFlags inFlags, QT3DSVec3 inWorldCenterPt, Qt3DSRendererImpl &gen, const QT3DSMat44 &inGlobalTransform, NVBounds3 &inBounds, SPath &inPath, const QT3DSMat44 &inModelViewProjection, - const QT3DSMat33 inNormalMat, const SGraphObject &inMaterial, QT3DSF32 inOpacity, - SShaderDefaultMaterialKey inShaderKey, bool inIsStroke) + const QT3DSMat33 inNormalMat, const SGraphObject &inMaterial, + QT3DSF32 inOpacity, SShaderDefaultMaterialKey inShaderKey, bool inIsStroke) : SRenderableObject(inFlags, inWorldCenterPt, inGlobalTransform, m_Bounds) , m_Generator(gen) diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp index db3697a..99d5c45 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp @@ -968,6 +968,20 @@ namespace render { return mouseVec; } + uint Qt3DSRendererImpl::getLayerTextureId(SLayer &layer) + { + SLayerRenderData *data = GetOrCreateLayerRenderDataForNode(layer); + if (data->m_LayerCachedTexture) { + return static_cast<uint>(reinterpret_cast<size_t>( + data->m_LayerCachedTexture->GetTextureObjectHandle())); + } + if (data->m_LayerTexture) { + return static_cast<uint>(reinterpret_cast<size_t>( + data->m_LayerTexture->GetTextureObjectHandle())); + } + return 0; + } + Option<SLayerPickSetup> Qt3DSRendererImpl::GetLayerPickSetup(SLayer &inLayer, const QT3DSVec2 &inMouseCoords, const QSize &inPickDims) @@ -1128,6 +1142,24 @@ namespace render { theShader->m_Dimensions.Set(inDimensions); theShader->m_Sampler.Set(&inQuadTexture); + // Set anaglyph color multiplier based on mode & current eye + // Default non-anaglyph modes use just vec4(1.0,1.0,1.0,1.0) + auto stereoMode = m_qt3dsContext.GetStereoMode(); + auto stereoView = m_qt3dsContext.GetStereoView(); + QT3DSVec4 anaglyphColor(1.0); + if (stereoMode == StereoModes::AnaglyphRedCyan) { + if (stereoView == StereoViews::Left) + anaglyphColor = QT3DSVec4(1.0, 0.0, 0.0, 0.0); + else + anaglyphColor = QT3DSVec4(0.0, 1.0, 1.0, 0.0); + } else if (stereoMode == StereoModes::AnaglyphGreenMagenta) { + if (stereoView == StereoViews::Left) + anaglyphColor = QT3DSVec4(0.0, 1.0, 0.0, 0.0); + else + anaglyphColor = QT3DSVec4(1.0, 0.0, 1.0, 0.0); + } + theShader->m_anaglyphColor.Set(anaglyphColor); + GenerateXYQuad(); theContext.SetInputAssembler(m_QuadInputAssembler); theContext.Draw(NVRenderDrawMode::Triangles, m_QuadIndexBuffer->GetNumIndices(), 0); diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h index cd104df..32c48d3 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h @@ -385,6 +385,8 @@ namespace render { const QT3DSVec3 &inMouseVec) const override; QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const override; + uint getLayerTextureId(SLayer &layer) override; + Option<SLayerPickSetup> GetLayerPickSetup(SLayer &inLayer, const QT3DSVec2 &inMouseCoords, const QSize &inPickDims) override; diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp index 2d11615..1626560 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp @@ -43,6 +43,7 @@ #include "Qt3DSRenderResourceManager.h" #include "Qt3DSTextRenderer.h" #include "Qt3DSRenderEffectSystem.h" +#include "Qt3DSRenderContextCore.h" #include "render/Qt3DSRenderFrameBuffer.h" #include "render/Qt3DSRenderRenderBuffer.h" #include "Qt3DSOffscreenRenderKey.h" @@ -1614,8 +1615,10 @@ namespace render { theFB->Attach(NVRenderFrameBufferAttachments::Color0, **renderColorTexture, thFboAttachTarget); - if (m_Layer.m_Background != LayerBackground::Unspecified) + if (m_Layer.m_Background != LayerBackground::Unspecified) { + theRenderContext.SetClearColor(clearColor); theRenderContext.Clear(clearFlags); + } // We don't clear the depth buffer because the layer render code we are about to call // will do this. @@ -1729,7 +1732,17 @@ namespace render { void SLayerRenderData::ApplyLayerPostEffects() { - if (m_Layer.m_FirstEffect == NULL) { + bool effectsActive = false; + SEffect *lastEffect = nullptr; + // Check if effects are active and get last active effect + for (SEffect *theEffect = m_Layer.m_FirstEffect; theEffect; + theEffect = theEffect->m_NextEffect) { + if (theEffect->m_Flags.IsActive()) { + effectsActive = true; + lastEffect = theEffect; + } + } + if (!effectsActive || !m_Camera) { if (m_LayerCachedTexture) { IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager()); theResourceManager.Release(*m_LayerCachedTexture); @@ -1744,16 +1757,29 @@ namespace render { NVRenderTexture2D *theLayerColorTexture = m_LayerTexture; NVRenderTexture2D *theLayerDepthTexture = m_LayerDepthTexture; + if (!m_LayerCachedTexture) { + STextureDetails details(theLayerColorTexture->GetTextureDetails()); + QT3DSU32 finalWidth = ITextRenderer::NextMultipleOf4((QT3DSU32)(details.m_Width)); + QT3DSU32 finalHeight = ITextRenderer::NextMultipleOf4((QT3DSU32)(details.m_Height)); + m_LayerCachedTexture = theResourceManager.AllocateTexture2D(finalWidth, finalHeight, + details.m_Format); + } + NVRenderTexture2D *theCurrentTexture = theLayerColorTexture; for (SEffect *theEffect = m_Layer.m_FirstEffect; theEffect; theEffect = theEffect->m_NextEffect) { - if (theEffect->m_Flags.IsActive() && m_Camera) { + if (theEffect->m_Flags.IsActive()) { + NVRenderTexture2D *targetTexture = nullptr; + if (theEffect == lastEffect) + targetTexture = m_LayerCachedTexture; + StartProfiling(theEffect->m_ClassName, false); NVRenderTexture2D *theRenderedEffect = theEffectSystem.RenderEffect( SEffectRenderArgument(*theEffect, *theCurrentTexture, QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar), - theLayerDepthTexture, m_LayerPrepassDepthTexture)); + theLayerDepthTexture, m_LayerPrepassDepthTexture, + targetTexture)); EndProfiling(theEffect->m_ClassName); @@ -1773,14 +1799,6 @@ namespace render { } } } - - if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture) { - theResourceManager.Release(*m_LayerCachedTexture); - m_LayerCachedTexture = NULL; - } - - if (theCurrentTexture != m_LayerTexture) - m_LayerCachedTexture = theCurrentTexture; } inline bool AnyCompletelyNonTransparentObjects(TRenderableObjectList &inObjects) diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp index c33aaeb..d69e46e 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.cpp @@ -2430,10 +2430,11 @@ namespace render { vertexGenerator.Append("}"); fragmentGenerator.AddUniform("layer_image", "sampler2D"); + fragmentGenerator.AddUniform("anaglyphColor", "vec4"); fragmentGenerator.Append("void main() {"); fragmentGenerator.Append("\tvec2 theCoords = uv_coords;\n"); fragmentGenerator.Append("\tvec4 theLayerTexture = texture2D( layer_image, theCoords );\n"); - fragmentGenerator.Append("\tfragOutput = theLayerTexture;\n"); + fragmentGenerator.Append("\tfragOutput = theLayerTexture * anaglyphColor;\n"); fragmentGenerator.Append("}"); NVRenderShaderProgram *theShader = GetProgramGenerator().CompileGeneratedShader( "layer shader", SShaderCacheProgramFlags(), TShaderFeatureSet()); diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h index 9753256..0d77121 100644 --- a/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h +++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplShaders.h @@ -341,7 +341,8 @@ namespace render { NVRenderCachedShaderProperty<QT3DSVec2> m_Dimensions; // The fourth member of text color is the opacity NVRenderCachedShaderProperty<NVRenderTexture2D *> m_Sampler; - + // Color multiplier for anaglyph stereo modes + NVRenderCachedShaderProperty<QT3DSVec4> m_anaglyphColor; volatile QT3DSI32 mRefCount; SLayerSceneShader(NVRenderShaderProgram &inShader) @@ -349,6 +350,7 @@ namespace render { , m_MVP("model_view_projection", inShader) , m_Dimensions("layer_dimensions", inShader) , m_Sampler("layer_image", inShader) + , m_anaglyphColor("anaglyphColor", inShader) , mRefCount(0) { m_Shader.addRef(); diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp index 353e585..577bd55 100644 --- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp +++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp @@ -225,9 +225,7 @@ SLoadedTexture *SLoadedTexture::LoadASTC(const QString &inPath, QT3DSI32 flipVer if (!astcFile.open(QIODevice::ReadOnly)) return nullptr; - QByteArray fileData = astcFile.readAll(); - - astcFile.close(); + QByteArray fileData = astcFile.read(sizeof(AstcHeader)); const AstcHeader *header = reinterpret_cast<const AstcHeader *>(fileData.constData()); int xSz = int(header->xSize[0]) | int(header->xSize[1]) << 8 | int(header->xSize[2]) << 16; @@ -259,8 +257,10 @@ SLoadedTexture *SLoadedTexture::LoadASTC(const QString &inPath, QT3DSI32 flipVer image->internalFormat = glFmt; image->format = runtimeFormat(glFmt); image->compressed = 1; + image->dataBlock = QT3DS_ALLOC(alloc, byteCount, "Qt3DSDDSAllocDataBlock"); - memcpy(image->dataBlock, fileData.constData() + sizeof(AstcHeader), byteCount); + astcFile.read(static_cast<char*>(image->dataBlock), byteCount); + astcFile.close(); retval->dds = image; retval->width = image->width; diff --git a/src/viewer/Qt3DSViewerApp.cpp b/src/viewer/Qt3DSViewerApp.cpp index 5916061..a4cec7f 100644 --- a/src/viewer/Qt3DSViewerApp.cpp +++ b/src/viewer/Qt3DSViewerApp.cpp @@ -1051,6 +1051,14 @@ void Q3DSViewerApp::addImageProvider(const QString &providerId, QQmlImageProvide m_Impl.m_view->addImageProvider(providerId, provider); } +uint Q3DSViewerApp::textureId(const QString &elementPath) +{ + if (!m_Impl.m_view) + return 0; + + return m_Impl.m_view->textureId(elementPath); +} + Q3DSViewerApp &Q3DSViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer, QElapsedTimer *startupTimer) { diff --git a/src/viewer/Qt3DSViewerApp.h b/src/viewer/Qt3DSViewerApp.h index d5b02e4..25d2ed7 100644 --- a/src/viewer/Qt3DSViewerApp.h +++ b/src/viewer/Qt3DSViewerApp.h @@ -95,7 +95,9 @@ struct ViewerStereoModes enum Enum { Mono, TopBottom, - LeftRight + LeftRight, + AnaglyphRedCyan, + AnaglyphGreenMagenta }; }; @@ -495,6 +497,8 @@ public: void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider); + uint textureId(const QString &elementPath); + QString error(); void setPresentationId(const QString &id); diff --git a/tools/viewer/main.cpp b/tools/viewer/main.cpp index 70da8fa..1bcbe9d 100644 --- a/tools/viewer/main.cpp +++ b/tools/viewer/main.cpp @@ -377,6 +377,10 @@ int main(int argc, char *argv[]) appWindow->setProperty("stereoMode", Q3DSViewerSettings::StereoModeTopBottom); else if (stereoStr == QStringLiteral("leftright")) appWindow->setProperty("stereoMode", Q3DSViewerSettings::StereoModeLeftRight); + else if (stereoStr == QStringLiteral("anaglyphredcyan")) + appWindow->setProperty("stereoMode", Q3DSViewerSettings::StereoModeAnaglyphRedCyan); + else if (stereoStr == QStringLiteral("anaglyphgreenmagenta")) + appWindow->setProperty("stereoMode", Q3DSViewerSettings::StereoModeAnaglyphGreenMagenta); else appWindow->setProperty("stereoMode", Q3DSViewerSettings::StereoModeMono); } diff --git a/tools/viewer/qml/main.qml b/tools/viewer/qml/main.qml index 1a59739..153753a 100644 --- a/tools/viewer/qml/main.qml +++ b/tools/viewer/qml/main.qml @@ -31,7 +31,7 @@ import QtQuick 2.7 import QtQuick.Controls 2.2 import QtQuick.Dialogs 1.2 import Qt3DStudioViewer 1.0 -import QtStudio3D.OpenGL 2.4 +import QtStudio3D.OpenGL 2.5 import QtQuick.Window 2.2 ApplicationWindow { @@ -570,6 +570,10 @@ ApplicationWindow { else if (window.stereoMode === ViewerSettings.StereoModeTopBottom) window.stereoMode = ViewerSettings.StereoModeLeftRight; else if (window.stereoMode === ViewerSettings.StereoModeLeftRight) + window.stereoMode = ViewerSettings.StereoModeAnaglyphRedCyan; + else if (window.stereoMode === ViewerSettings.StereoModeAnaglyphRedCyan) + window.stereoMode = ViewerSettings.StereoModeAnaglyphGreenMagenta; + else if (window.stereoMode === ViewerSettings.StereoModeAnaglyphGreenMagenta) window.stereoMode = ViewerSettings.StereoModeMono; } } @@ -610,6 +614,26 @@ ApplicationWindow { } } StyledMenuItem { + id: stereoAnaglyphRedCyan + text: qsTr("Anaglyph (Red-Cyan)") + enabled: _viewerHelper.contentView === ViewerHelper.StudioView + showCheckMark: window.stereoMode === ViewerSettings.StereoModeAnaglyphRedCyan + onTriggered: { + if (enabled) + window.stereoMode = ViewerSettings.StereoModeAnaglyphRedCyan; + } + } + StyledMenuItem { + id: stereoAnaglyphGreenMagenta + text: qsTr("Anaglyph (Green-Magenta)") + enabled: _viewerHelper.contentView === ViewerHelper.StudioView + showCheckMark: window.stereoMode === ViewerSettings.StereoModeAnaglyphGreenMagenta + onTriggered: { + if (enabled) + window.stereoMode = ViewerSettings.StereoModeAnaglyphGreenMagenta; + } + } + StyledMenuItem { id: stereoEyeSeparationUp text: qsTr("Increase Separation") shortcut: "Ctrl+Shift++" |