summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--Studio/Content/Material Library/aluminium_anodized.shader2
-rw-r--r--Studio/Content/Material Library/aluminium_anodized_emissive.shader13
-rw-r--r--Studio/Content/Material Library/aluminum.shader12
-rw-r--r--Studio/Content/Material Library/aluminum_anisotropic.shader14
-rw-r--r--Studio/Content/Material Library/aluminum_brushed.shader16
-rw-r--r--Studio/Content/Material Library/aluminum_emissive.shader25
-rw-r--r--Studio/Content/Material Library/aluminum_textured_aniso.shader16
-rw-r--r--Studio/Content/Material Library/asphalt.shader14
-rw-r--r--Studio/Content/Material Library/bamboo_natural_matte.shader18
-rw-r--r--Studio/Content/Material Library/bamboo_natural_matte_emissive.shader23
-rw-r--r--Studio/Content/Material Library/carbon_fiber.shader31
-rw-r--r--Studio/Content/Material Library/carbon_fiber_emissive.shader32
-rw-r--r--Studio/Content/Material Library/carpaint_blue_standard.shader6
-rw-r--r--Studio/Content/Material Library/carpaint_color_peel_2_layer.shader8
-rw-r--r--Studio/Content/Material Library/carpaint_yellow_standard.shader6
-rw-r--r--Studio/Content/Material Library/concrete.shader17
-rw-r--r--Studio/Content/Material Library/copper.shader2
-rw-r--r--Studio/Content/Material Library/leather_smoothed_black.shader17
-rw-r--r--Studio/Content/Material Library/mesh_fence.shader17
-rw-r--r--Studio/Content/Material Library/metal_mesh_fine.shader19
-rw-r--r--Studio/Content/Material Library/paper_artistic.shader17
-rw-r--r--Studio/Content/Material Library/paper_office.shader13
-rw-r--r--Studio/Content/Material Library/plastic_structured_red.shader6
-rw-r--r--Studio/Content/Material Library/plastic_structured_red_emissive.shader15
-rw-r--r--Studio/Content/Material Library/porcelain.shader4
-rw-r--r--Studio/Content/Material Library/powder_coat.shader6
-rw-r--r--Studio/Content/Material Library/powder_coat_emissive.shader10
-rw-r--r--Studio/Content/Material Library/rubber_studded_black.shader6
-rw-r--r--Studio/Content/Material Library/rubber_studded_emissive.shader20
-rw-r--r--Studio/Content/Material Library/simple_glass.shader2
-rw-r--r--Studio/Content/Material Library/steel_milled_concentric.shader25
-rw-r--r--Studio/Content/Material Library/thin_glass_frosted.shader8
-rw-r--r--Studio/Content/Material Library/thin_glass_frosted_sp.shader10
-rw-r--r--Studio/Content/Material Library/thin_glass_refractive.shader2
-rw-r--r--Studio/Content/Material Library/walnut_matte.shader16
-rw-r--r--commonplatform.pri15
-rw-r--r--examples/studio3d/dynamicelement/presentation/materials/copper.shader2
-rw-r--r--examples/studio3d/simpleqml/main.qml8
-rw-r--r--examples/studio3d/simpleqml/presentation/barrel.uip67
-rw-r--r--ogl-runtime.pro3
-rw-r--r--product_dependencies.yaml3
-rw-r--r--res.qrc6
-rw-r--r--res/DataModelMetadata/en-us/MetaData.xml24
-rw-r--r--res/effectlib/customMaterial.glsllib3
-rw-r--r--res/effectlib/defaultMaterialFresnel.glsllib6
-rw-r--r--res/effectlib/distancefieldtext.frag4
-rw-r--r--res/effectlib/distancefieldtext_core.frag4
-rw-r--r--res/effectlib/distancefieldtext_dropshadow.frag8
-rw-r--r--res/effectlib/distancefieldtext_dropshadow_core.frag8
-rw-r--r--res/effectlib/evalBakedShadowMap.glsllib2
-rw-r--r--res/effectlib/funcdiffuseReflectionBSDF.glsllib39
-rw-r--r--res/effectlib/funcsampleAreaGlossyDefault.glsllib29
-rw-r--r--res/effectlib/funcsampleNormalTexture.glsllib6
-rw-r--r--res/effectlib/funcspecularBSDF.glsllib40
-rw-r--r--res/effectlib/gles2/sampleProbe.glsllib482
-rw-r--r--res/effectlib/gles2/sampleProbePre.glsllib7
-rw-r--r--res/effectlib/luminance.glsllib28
-rw-r--r--res/effectlib/sampleProbe.glsllib398
-rw-r--r--res/effectlib/sampleProbePre.glsllib5
-rw-r--r--res/effectlib/specularBSDF.glsllib18
-rw-r--r--res/effectlib/transformCoordinate.glsllib9
m---------src/3rdparty/EASTL0
-rw-r--r--src/api/studio3d/doc/qt3dstudio-opengl-runtime-project.qdocconf8
-rw-r--r--src/api/studio3d/doc/src/building-opengl-runtime.qdoc55
-rw-r--r--src/api/studio3d/doc/src/gettingstarted.qdoc5
-rw-r--r--src/api/studio3d/q3dscommandqueue.cpp15
-rw-r--r--src/api/studio3d/q3dscommandqueue_p.h6
-rw-r--r--src/api/studio3d/q3dsdatainput.cpp40
-rw-r--r--src/api/studio3d/q3dsdatainput.h2
-rw-r--r--src/api/studio3d/q3dsgeometry.cpp4
-rw-r--r--src/api/studio3d/q3dspresentation.cpp353
-rw-r--r--src/api/studio3d/q3dspresentation.h9
-rw-r--r--src/api/studio3d/q3dspresentation_p.h5
-rw-r--r--src/api/studio3d/q3dssceneelement.cpp24
-rw-r--r--src/api/studio3d/q3dssurfaceviewer.cpp28
-rw-r--r--src/api/studio3d/q3dssurfaceviewer.h1
-rw-r--r--src/api/studio3d/q3dsviewersettings.cpp222
-rw-r--r--src/api/studio3d/q3dsviewersettings.h12
-rw-r--r--src/api/studio3d/q3dsviewersettings_p.h6
-rw-r--r--src/api/studio3d/studio3d.pro6
-rw-r--r--src/api/studio3dqml/plugins.qmltypes234
-rw-r--r--src/api/studio3dqml/q3dsplugin.cpp13
-rw-r--r--src/api/studio3dqml/q3dsrenderer.cpp25
-rw-r--r--src/api/studio3dqml/q3dsrenderer_p.h4
-rw-r--r--src/api/studio3dqml/q3dsstudio3d.cpp14
-rw-r--r--src/api/studio3dqml/q3dsstudio3d_p.h2
-rw-r--r--src/api/studio3dqml/studio3dqml.pro6
-rw-r--r--src/dm/dm.pro4
-rw-r--r--src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp11
-rw-r--r--src/dm/systems/Qt3DSDMComposerTypeDefinitions.h29
-rw-r--r--src/dm/systems/Qt3DSDMMetaData.cpp117
-rw-r--r--src/dm/systems/Qt3DSDMMetaData.h1
-rw-r--r--src/dm/systems/Qt3DSDMSlideCore.h45
-rw-r--r--src/dm/systems/SlideSystem.cpp5
-rw-r--r--src/dm/systems/cores/DataCoreProducer.cpp16
-rw-r--r--src/dm/systems/cores/SimpleDataCore.h24
-rw-r--r--src/dm/systems/cores/SimpleSlideCore.h27
-rw-r--r--src/dm/systems/cores/SlideCoreProducer.cpp5
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.cpp258
-rw-r--r--src/engine/Qt3DSRenderRuntimeBinding.h4
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImpl.h5
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp39
-rw-r--r--src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp113
-rw-r--r--src/engine/Qt3DSRuntimeView.cpp101
-rw-r--r--src/engine/Qt3DSRuntimeView.h13
-rw-r--r--src/foundation/Qt3DSAllocator.h4
-rw-r--r--src/foundation/Qt3DSPerfTimer.cpp41
-rw-r--r--src/foundation/Qt3DSPerfTimer.h7
-rw-r--r--src/foundation/StringTable.h2
-rw-r--r--src/ogl-runtime-dylib/ogl-runtime-dylib.pro6
-rw-r--r--src/ogl-runtime-static/ogl-runtime-static.pro8
-rw-r--r--src/qmlstreamer/q3dsqmlstream.cpp8
-rw-r--r--src/qmlstreamer/q3dsqmlstreamrenderer.cpp12
-rw-r--r--src/qmlstreamer/q3dsqmlsubpresentationsettings.cpp2
-rw-r--r--src/qmlstreamer/qmlstreamer.pro6
-rw-r--r--src/render/Qt3DSRenderBaseTypes.h179
-rw-r--r--src/render/Qt3DSRenderContext.h8
-rw-r--r--src/render/Qt3DSRenderShaderProgram.cpp3
-rw-r--r--src/render/Qt3DSRenderTexture2D.cpp10
-rw-r--r--src/render/backends/gl/Qt3DSOpenGLUtil.h2
-rw-r--r--src/render/backends/gl/Qt3DSRenderBackendGLBase.cpp62
-rw-r--r--src/render/backends/gl/Qt3DSRenderContextGL.cpp61
-rw-r--r--src/runtime/Qt3DSActivationManager.cpp129
-rw-r--r--src/runtime/Qt3DSAnimationSystem.cpp2
-rw-r--r--src/runtime/Qt3DSAnimationSystem.h2
-rw-r--r--src/runtime/Qt3DSApplication.cpp245
-rw-r--r--src/runtime/Qt3DSApplication.h17
-rw-r--r--src/runtime/Qt3DSAttributeHashes.cpp16
-rw-r--r--src/runtime/Qt3DSAttributeHashes.h16
-rw-r--r--src/runtime/Qt3DSAttributeHashes.txt18
-rw-r--r--src/runtime/Qt3DSComponentManager.cpp85
-rw-r--r--src/runtime/Qt3DSComponentManager.h13
-rw-r--r--src/runtime/Qt3DSElementHelper.cpp141
-rw-r--r--src/runtime/Qt3DSElementHelper.h57
-rw-r--r--src/runtime/Qt3DSElementSystem.cpp167
-rw-r--r--src/runtime/Qt3DSElementSystem.h110
-rw-r--r--src/runtime/Qt3DSIComponentManager.h9
-rw-r--r--src/runtime/Qt3DSIScene.h2
-rw-r--r--src/runtime/Qt3DSIScriptBridge.h8
-rw-r--r--src/runtime/Qt3DSInputEventTypes.h3
-rw-r--r--src/runtime/Qt3DSKernelTypes.h9
-rw-r--r--src/runtime/Qt3DSLogicSystem.cpp10
-rw-r--r--src/runtime/Qt3DSPresentation.cpp26
-rw-r--r--src/runtime/Qt3DSPresentation.h10
-rw-r--r--src/runtime/Qt3DSQmlElementHelper.cpp146
-rw-r--r--src/runtime/Qt3DSQmlElementHelper.h10
-rw-r--r--src/runtime/Qt3DSQmlEngine.cpp441
-rw-r--r--src/runtime/Qt3DSQmlEngine.h2
-rw-r--r--src/runtime/Qt3DSSlideSystem.cpp17
-rw-r--r--src/runtime/Qt3DSSlideSystem.h1
-rw-r--r--src/runtime/q3dsqmlscript.cpp12
-rw-r--r--src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp48
-rw-r--r--src/runtimerender/Qt3DSDistanceFieldGlyphCache_p.h10
-rw-r--r--src/runtimerender/Qt3DSDistanceFieldRenderer.cpp127
-rw-r--r--src/runtimerender/Qt3DSQtTextRenderer.cpp7
-rw-r--r--src/runtimerender/Qt3DSRenderContextCore.cpp198
-rw-r--r--src/runtimerender/Qt3DSRenderContextCore.h15
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp86
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp271
-rw-r--r--src/runtimerender/Qt3DSRenderCustomMaterialSystem.h2
-rw-r--r--src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp372
-rw-r--r--src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp83
-rw-r--r--src/runtimerender/Qt3DSRenderDynamicObjectSystem.h3
-rw-r--r--src/runtimerender/Qt3DSRenderDynamicObjectSystemCommands.h40
-rw-r--r--src/runtimerender/Qt3DSRenderEffectSystem.cpp162
-rw-r--r--src/runtimerender/Qt3DSRenderGraphObjectSerializer.cpp143
-rw-r--r--src/runtimerender/Qt3DSRenderInputStreamFactory.cpp9
-rw-r--r--src/runtimerender/Qt3DSRenderInputStreamFactory.h1
-rw-r--r--src/runtimerender/Qt3DSRenderMaterialHelpers.h4
-rw-r--r--src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h4
-rw-r--r--src/runtimerender/Qt3DSRenderShaderCache.cpp105
-rw-r--r--src/runtimerender/Qt3DSRenderShaderCache.h2
-rw-r--r--src/runtimerender/Qt3DSRenderSubpresentation.cpp7
-rw-r--r--src/runtimerender/Qt3DSRenderTextTextureCache.cpp76
-rw-r--r--src/runtimerender/Qt3DSRenderTextTypes.h2
-rw-r--r--src/runtimerender/Qt3DSRenderUIPLoader.cpp79
-rw-r--r--src/runtimerender/Qt3DSRenderUIPLoader.h2
-rw-r--r--src/runtimerender/Qt3DSRenderUIPSharedTranslation.cpp70
-rw-r--r--src/runtimerender/Qt3DSRenderUIPSharedTranslation.h33
-rw-r--r--src/runtimerender/Qt3DSRenderer.h9
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h25
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp1
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h11
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp53
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h44
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp3
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderEffect.h18
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderImage.cpp38
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderImage.h5
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderLayer.cpp5
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderLayer.h6
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderNode.cpp96
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderNode.h32
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderPresentation.h3
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderScene.cpp5
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderScene.h3
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderText.cpp1
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp35
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h23
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp167
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImpl.h13
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp497
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h20
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp119
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h18
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp406
-rw-r--r--src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h21
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp566
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h46
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp80
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h11
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp58
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h3
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureHDR.cpp39
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp2
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.cpp346
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.h9
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.cpp42
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.h14
-rw-r--r--src/system/Qt3DSHash.h37
-rw-r--r--src/uipparser/Qt3DSIPresentation.h3
-rw-r--r--src/uipparser/Qt3DSUIPParser.h3
-rw-r--r--src/uipparser/Qt3DSUIPParserActionHelper.cpp2
-rw-r--r--src/uipparser/Qt3DSUIPParserImpl.cpp157
-rw-r--r--src/uipparser/Qt3DSUIPParserImpl.h13
-rw-r--r--src/viewer/Qt3DSViewerApp.cpp59
-rw-r--r--src/viewer/Qt3DSViewerApp.h16
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestBase.cpp2
-rw-r--r--tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp128
-rw-r--r--tests/auto/studio3d/shared/maps/OpenfootageNET_garage-512.hdrbin0 -> 422659 bytes
-rw-r--r--tests/auto/studio3d/shared/presentation/activateactions.uip55
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.h1
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.qrc2
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp2
-rw-r--r--tools/viewer/main.cpp5
-rw-r--r--tools/viewer/qml/main.qml43
-rw-r--r--tools/viewer/viewer.pro13
238 files changed, 6888 insertions, 4262 deletions
diff --git a/.qmake.conf b/.qmake.conf
index c40e135..b89275b 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,5 +1,5 @@
load(qt_build_config)
-MODULE_VERSION = 2.6.0
+MODULE_VERSION = 2.8.0
CMAKE_MODULE_TESTS=-
diff --git a/Studio/Content/Material Library/aluminium_anodized.shader b/Studio/Content/Material Library/aluminium_anodized.shader
index 17da9fb..62511a6 100644
--- a/Studio/Content/Material Library/aluminium_anodized.shader
+++ b/Studio/Content/Material Library/aluminium_anodized.shader
@@ -93,7 +93,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
diff --git a/Studio/Content/Material Library/aluminium_anodized_emissive.shader b/Studio/Content/Material Library/aluminium_anodized_emissive.shader
index 1c3233f..444f620 100644
--- a/Studio/Content/Material Library/aluminium_anodized_emissive.shader
+++ b/Studio/Content/Material Library/aluminium_anodized_emissive.shader
@@ -68,7 +68,8 @@ struct texture_return
// temporary declarations
-texture_coordinate_info tmp3;
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
vec4 tmpShadowTerm;
layer_result layers[1];
@@ -99,7 +100,8 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3(1.0) * vec3( vec3( ( intensity *( emission_color.rgb * ( fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp3, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint * fileTexture(emissive_mask_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp3, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp1, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint
+ * fileTexture(emissive_mask_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp2, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
@@ -128,7 +130,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
@@ -182,8 +184,9 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp1 = textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal );
+ tmp2 = textureCoordinateInfo( texcoordTransformed_emissive_mask_texture(texCoord0), tangent, binormal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/aluminum.shader b/Studio/Content/Material Library/aluminum.shader
index e2a5bea..efd61fb 100644
--- a/Studio/Content/Material Library/aluminum.shader
+++ b/Studio/Content/Material Library/aluminum.shader
@@ -73,9 +73,10 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp1;
+texture_coordinate_info tmp3;
float tmp2;
float ftmp0;
- vec4 tmpShadowTerm;
+vec4 tmpShadowTerm;
layer_result layers[1];
@@ -135,7 +136,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, tmp2, tmp2 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, tmp2 );
#endif
}
@@ -184,14 +185,15 @@ float evalCutout()
vec3 computeNormal()
{
- return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
}
void computeTemporaries()
{
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), tiling ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_roughness_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_reflection_texture(texCoord0), tangent, binormal ) );
tmp2 = fileTexture(roughness_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
- ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/aluminum_anisotropic.shader b/Studio/Content/Material Library/aluminum_anisotropic.shader
index b5fed9f..c9d604e 100644
--- a/Studio/Content/Material Library/aluminum_anisotropic.shader
+++ b/Studio/Content/Material Library/aluminum_anisotropic.shader
@@ -84,6 +84,8 @@ struct anisotropy_return
// temporary declarations
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
texture_return tmp4;
anisotropy_return tmp5;
@@ -135,7 +137,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
#endif
}
@@ -160,7 +162,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, ftmp0 );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -217,9 +219,11 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( tiling[0], tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp4 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
- tmp5 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
+ tmp1 = scaleCoordinate(vec3( tiling[0], tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_aniso_rot_texture(texCoord0), tangent, binormal ) );
+ tmp2 = scaleCoordinate(vec3( tiling[0], tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_reflection_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(vec3( tiling[0], tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp4 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
+ tmp5 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
tmp6 = tmp4.tint;
tmp8 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
ftmp0 = tmp5.roughness_u;
diff --git a/Studio/Content/Material Library/aluminum_brushed.shader b/Studio/Content/Material Library/aluminum_brushed.shader
index 594b4fa..079c159 100644
--- a/Studio/Content/Material Library/aluminum_brushed.shader
+++ b/Studio/Content/Material Library/aluminum_brushed.shader
@@ -72,6 +72,9 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
float ftmp0;
float ftmp1;
float ftmp2;
@@ -135,7 +138,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp1, ftmp2 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, ftmp1 );
#endif
}
@@ -189,10 +192,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), tiling ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- ftmp0 = fileTexture(brush_texture, vec3( 0.5, 0.5, 0.5 ), vec3( 0.5, 0.5, 0.5 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
- ftmp1 = fileTexture(roughness_texture_u, vec3( 0.12, 0.12, 0.12 ), vec3( ( 0.800000*brushing_strength ) ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
- ftmp2 = fileTexture(roughness_texture_v, vec3( ( 0.150000+( 0.400000*reflection_stretch ) ) ), vec3( ( 0.100000+( reflection_stretch*0.300000 ) ) ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_brush_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_roughness_texture_u(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_roughness_texture_v(texCoord0), tangent, binormal ) );
+ ftmp0 = fileTexture(brush_texture, vec3( 0.5, 0.5, 0.5 ), vec3( 0.5, 0.5, 0.5 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp1 = fileTexture(roughness_texture_u, vec3( 0.12, 0.12, 0.12 ), vec3( ( 0.800000*brushing_strength ) ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp2 = fileTexture(roughness_texture_v, vec3( ( 0.150000+( 0.400000*reflection_stretch ) ) ), vec3( ( 0.100000+( reflection_stretch*0.300000 ) ) ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/aluminum_emissive.shader b/Studio/Content/Material Library/aluminum_emissive.shader
index ed48012..15645cb 100644
--- a/Studio/Content/Material Library/aluminum_emissive.shader
+++ b/Studio/Content/Material Library/aluminum_emissive.shader
@@ -79,7 +79,9 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp1;
texture_coordinate_info tmp2;
-float tmp3;
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
+float tmp5;
float ftmp0;
vec4 tmpShadowTerm;
@@ -112,14 +114,15 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity*( emission_color.rgb *( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.0, 0.0, 0.0 ), vec3( 0.0, 0.0, 0.0 ), vec3( 1.0, 1.0, 1.0 ) ), tmp1 ), vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).tint*fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.0, 0.0, 0.0 ), emissive_mask_offset, vec3( 1.0, 1.0, 1.0 ) ), tmp1 ), vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp1, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).tint
+ * fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp2, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, tmp3, tmp3, scatter_reflect );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, tmp5, tmp5, scatter_reflect );
#endif
}
@@ -128,7 +131,7 @@ void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 light
{
#if QT3DS_ENABLE_CG_LIGHTING
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, tmp3, tmp3 );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, tmp5, tmp5 );
#endif
}
@@ -137,11 +140,11 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
{
#if !QT3DS_ENABLE_LIGHT_PROBE
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, tmp3, tmp3, scatter_reflect );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, tmp5, tmp5, scatter_reflect );
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, tmp3, tmp3 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, tmp5 );
#endif
}
@@ -195,10 +198,12 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp1 = textureCoordinateInfo( texCoord0, tangent, binormal );
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.0, 0.0, 0.0 ), vec3( 0.0, 0.0, 0.0 ), tiling ), tmp1 );
- tmp3 = fileTexture(roughness_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp2, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
- ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp2, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ tmp1 = textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal );
+ tmp2 = textureCoordinateInfo( texcoordTransformed_emissive_mask_texture(texCoord0), tangent, binormal );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_roughness_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_reflection_texture(texCoord0), tangent, binormal ) );
+ tmp5 = fileTexture(roughness_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp3, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
+ ftmp0 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp4, vec2( 0.0, 1.0 ), vec2( 0.0, 1.0 ), wrap_repeat, wrap_repeat, gamma_default ).mono;
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/aluminum_textured_aniso.shader b/Studio/Content/Material Library/aluminum_textured_aniso.shader
index ed9fb88..49973e4 100644
--- a/Studio/Content/Material Library/aluminum_textured_aniso.shader
+++ b/Studio/Content/Material Library/aluminum_textured_aniso.shader
@@ -85,8 +85,9 @@ struct anisotropy_return
// temporary declarations
-texture_coordinate_info tmp2;
texture_coordinate_info tmp4;
+texture_coordinate_info tmp11;
+texture_coordinate_info tmp12;
texture_return tmp5;
anisotropy_return tmp7;
vec3 tmp8;
@@ -137,7 +138,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
#endif
}
@@ -162,7 +163,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, ftmp0 );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -219,12 +220,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = textureCoordinateInfo( texCoord0, tangent, binormal );
- tmp4 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( tiling[0], tiling[1], 1.000000 ) ), tmp2 );
+ tmp4 = scaleCoordinate(vec3( tiling[0], tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_reflection_texture(texCoord0), tangent, binormal ) );
+ tmp11 = scaleCoordinate(vec3( tiling[0], tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp12 = scaleCoordinate(vec3( aniso_tiling[0], aniso_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_aniso_rot_texture(texCoord0), tangent, binormal ) );
tmp5 = fileTexture(reflection_texture, vec3( reflection_map_offset ), vec3( reflection_map_scale ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
- tmp7 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( aniso_tiling[0], aniso_tiling[1], 1.000000 ) ), tmp2 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
+ tmp7 = anisotropyConversion( fileTexture(reflection_texture, vec3( roughness_map_offset ), vec3( roughness_map_scale ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, anisotropy, fileTexture(aniso_rot_texture, vec3( aniso_tex_color_offset ), vec3( aniso_tex_color_scale ), mono_luminance, tmp12, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).mono, tangent, false );
tmp8 = tmp5.tint;
- tmp10 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmp10 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp11, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
ftmp0 = tmp7.roughness_u;
ftmp1 = tmp7.roughness_v;
ftmp2 = tmp7.tangent_u;
diff --git a/Studio/Content/Material Library/asphalt.shader b/Studio/Content/Material Library/asphalt.shader
index da37ed4..e4ee412 100644
--- a/Studio/Content/Material Library/asphalt.shader
+++ b/Studio/Content/Material Library/asphalt.shader
@@ -70,6 +70,8 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
vec3 tmp5;
vec3 ftmp0;
vec3 ftmp1;
@@ -115,7 +117,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -140,7 +142,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness);
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -197,10 +199,12 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
+ tmp2 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/bamboo_natural_matte.shader b/Studio/Content/Material Library/bamboo_natural_matte.shader
index 28ab611..aefadcd 100644
--- a/Studio/Content/Material Library/bamboo_natural_matte.shader
+++ b/Studio/Content/Material Library/bamboo_natural_matte.shader
@@ -70,6 +70,8 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
vec3 tmp5;
vec3 ftmp0;
vec3 ftmp1;
@@ -115,7 +117,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -140,7 +142,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -197,11 +199,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp2 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/bamboo_natural_matte_emissive.shader b/Studio/Content/Material Library/bamboo_natural_matte_emissive.shader
index 7096c14..2ffae65 100644
--- a/Studio/Content/Material Library/bamboo_natural_matte_emissive.shader
+++ b/Studio/Content/Material Library/bamboo_natural_matte_emissive.shader
@@ -75,6 +75,8 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
+texture_coordinate_info tmp5;
vec3 tmp6;
vec3 ftmp0;
vec3 ftmp1;
@@ -111,7 +113,7 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3(1.0) * vec3( vec3( ( intensity *( emission_color.rgb * fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, transformCoordinate( rotationTranslationScale( vec3(0.0), vec3(0.0), vec3(1.0) ), tmp2 ), vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp2, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor(in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor)
@@ -120,7 +122,7 @@ void computeFrontLayerColor(in vec3 normal, in vec3 lightDir, in vec3 viewDir, i
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, lightDiffuse );
#endif
}
@@ -145,7 +147,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -202,12 +204,15 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = textureCoordinateInfo( texCoord0, tangent, binormal );
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp2 );
- tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp5, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/carbon_fiber.shader b/Studio/Content/Material Library/carbon_fiber.shader
index fd3eca3..c1d5e74 100644
--- a/Studio/Content/Material Library/carbon_fiber.shader
+++ b/Studio/Content/Material Library/carbon_fiber.shader
@@ -83,6 +83,9 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp0;
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
anisotropy_return tmp4;
vec3 tmp6;
@@ -136,7 +139,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
layers[2].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, lightDiffuse );
#endif
}
@@ -165,9 +168,9 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[2].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, coat_roughness );
- layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, ftmp0, ftmp1 );
+ layers[1].layer += tmpShadowTerm * sampleGlossy( layers[1].tanFrame, viewDir, ftmp0 );
layers[2].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[2].layer += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
@@ -224,15 +227,19 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp4 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
- tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = tmp4.roughness_u;
- ftmp1 = tmp4.roughness_v;
- ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp3 = tmp4.tangent_u;
- ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp0 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_anisotropy_rotation_texture(texCoord0), tangent, binormal ) );
+ tmp4 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp0, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp4.roughness_u;
+ ftmp1 = tmp4.roughness_v;
+ ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp4.tangent_u;
+ ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/carbon_fiber_emissive.shader b/Studio/Content/Material Library/carbon_fiber_emissive.shader
index fae9b7b..b5e1a03 100644
--- a/Studio/Content/Material Library/carbon_fiber_emissive.shader
+++ b/Studio/Content/Material Library/carbon_fiber_emissive.shader
@@ -20,7 +20,6 @@
<Property formalName="Intensity" name="intensity" description="Emission intensity" type="Float" default="1.000000" category="Material"/>
<Property formalName="Emission Color" name="emission_color" description="Color of the emission" type="Color" default="0 0 0" category="Material"/>
<Property formalName="Emissive Map" name="emissive_texture" description="Emissive texture of the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive" default="./maps/materials/emissive.png" category="Material"/>
- <Property formalName="Emissive Mask Map" name="emissive_mask_texture" description="Emissive mask texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="emissive_mask" category="Material"/>
</MetaData>
<Shaders type="GLSL" version="330">
<Shader>
@@ -87,6 +86,7 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
texture_coordinate_info tmp4;
anisotropy_return tmp5;
@@ -130,7 +130,7 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity *( emission_color.rgb * fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
@@ -141,7 +141,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
layers[2].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp7, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[2].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp7, lightDir, lightDiffuse );
#endif
}
@@ -170,9 +170,9 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[2].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp7, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, coat_roughness );
- layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, ftmp0, ftmp1 );
+ layers[1].layer += tmpShadowTerm * sampleGlossy( layers[1].tanFrame, viewDir, ftmp0 );
layers[2].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[2].layer += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
@@ -229,16 +229,18 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
- tmp4 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp3 );
- tmp5 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
- tmp7 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = tmp5.roughness_u;
- ftmp1 = tmp5.roughness_v;
- ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp3 = tmp5.tangent_u;
- ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.000000 );
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_anisotropy_rotation_texture(texCoord0), tangent, binormal ) );
+ tmp5 = anisotropyConversion( base_roughness, anisotropy, fileTexture(anisotropy_rotation_texture, vec3( 0, 0, 0 ), vec3( 3.14, 3.14, 3.14 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ tmp7 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = tmp5.roughness_u;
+ ftmp1 = tmp5.roughness_v;
+ ftmp2 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp5.tangent_u;
+ ftmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/carpaint_blue_standard.shader b/Studio/Content/Material Library/carpaint_blue_standard.shader
index b28a814..87f5642 100644
--- a/Studio/Content/Material Library/carpaint_blue_standard.shader
+++ b/Studio/Content/Material Library/carpaint_blue_standard.shader
@@ -110,7 +110,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
#if QT3DS_ENABLE_CG_LIGHTING
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect );
- layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 ) );
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, diffuseReflectionBSDF( normal, lightDir, lightDiffuse ) );
layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.200000, 0.200000, scatter_reflect );
#endif
@@ -136,10 +136,10 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, 0.200000, 0.200000, scatter_reflect );
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, 0.000000 );
layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, sampleDiffuse( layers[1].tanFrame ) * aoFactor );
- layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, 0.200000, 0.200000 );
+ layers[1].layer += tmpShadowTerm * sampleGlossy( layers[1].tanFrame, viewDir, 0.200000 );
#endif
}
diff --git a/Studio/Content/Material Library/carpaint_color_peel_2_layer.shader b/Studio/Content/Material Library/carpaint_color_peel_2_layer.shader
index c435306..7bc5818 100644
--- a/Studio/Content/Material Library/carpaint_color_peel_2_layer.shader
+++ b/Studio/Content/Material Library/carpaint_color_peel_2_layer.shader
@@ -122,7 +122,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, flake_roughness, flake_roughness, scatter_reflect );
- layers[2].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[2].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
layers[2].layer += tmpShadowTerm * microfacetBSDF( layers[2].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.300000, 0.300000, scatter_reflect );
#endif
@@ -152,12 +152,12 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[2].layer += tmpShadowTerm * microfacetSampledBSDF( layers[2].tanFrame, viewDir, 0.300000, 0.300000, scatter_reflect );
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, coat_roughness, coat_roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, coat_roughness );
- layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, flake_roughness, flake_roughness );
+ layers[1].layer += tmpShadowTerm * sampleGlossy( layers[1].tanFrame, viewDir, flake_roughness );
layers[2].base += tmpShadowTerm * sampleDiffuse( layers[2].tanFrame ) * aoFactor;
- layers[2].layer += tmpShadowTerm * sampleGlossyAniso( layers[2].tanFrame, viewDir, 0.300000, 0.300000 );
+ layers[2].layer += tmpShadowTerm * sampleGlossy( layers[2].tanFrame, viewDir, 0.300000 );
#endif
}
diff --git a/Studio/Content/Material Library/carpaint_yellow_standard.shader b/Studio/Content/Material Library/carpaint_yellow_standard.shader
index 7e79511..e6e6232 100644
--- a/Studio/Content/Material Library/carpaint_yellow_standard.shader
+++ b/Studio/Content/Material Library/carpaint_yellow_standard.shader
@@ -110,7 +110,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
#if QT3DS_ENABLE_CG_LIGHTING
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.000000, 0.000000, scatter_reflect );
- layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 ) );
+ layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, diffuseReflectionBSDF( normal, lightDir, lightDiffuse ) );
layers[1].layer += tmpShadowTerm * microfacetBSDF( layers[1].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, 0.200000, 0.200000, scatter_reflect );
#endif
@@ -136,10 +136,10 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * microfacetSampledBSDF( layers[1].tanFrame, viewDir, 0.200000, 0.200000, scatter_reflect );
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, 0.000000 );
layers[1].base += tmpShadowTerm * directionalFactor( normal, viewDir, normal_base_color.rgb, grazing_base_color.rgb, 5.000000, sampleDiffuse( layers[1].tanFrame ) * aoFactor );
- layers[1].layer += tmpShadowTerm * sampleGlossyAniso( layers[1].tanFrame, viewDir, 0.200000, 0.200000 );
+ layers[1].layer += tmpShadowTerm * sampleGlossy( layers[1].tanFrame, viewDir, 0.200000 );
#endif
}
diff --git a/Studio/Content/Material Library/concrete.shader b/Studio/Content/Material Library/concrete.shader
index 1bcdadc..7d215cf 100644
--- a/Studio/Content/Material Library/concrete.shader
+++ b/Studio/Content/Material Library/concrete.shader
@@ -68,6 +68,7 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
vec3 tmp6;
vec3 ftmp0;
@@ -114,7 +115,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, lightDiffuse );
#endif
}
@@ -139,7 +140,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -196,11 +197,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(bump_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(bump_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/copper.shader b/Studio/Content/Material Library/copper.shader
index cf9e1ad..24d7d32 100644
--- a/Studio/Content/Material Library/copper.shader
+++ b/Studio/Content/Material Library/copper.shader
@@ -93,7 +93,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
diff --git a/Studio/Content/Material Library/leather_smoothed_black.shader b/Studio/Content/Material Library/leather_smoothed_black.shader
index 8d45669..e5d876a 100644
--- a/Studio/Content/Material Library/leather_smoothed_black.shader
+++ b/Studio/Content/Material Library/leather_smoothed_black.shader
@@ -70,6 +70,8 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
+texture_coordinate_info tmp4;
vec3 tmp5;
vec3 ftmp0;
vec3 ftmp1;
@@ -115,7 +117,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -140,7 +142,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -197,10 +199,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp4 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp4, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/mesh_fence.shader b/Studio/Content/Material Library/mesh_fence.shader
index df5d817..5565fd2 100644
--- a/Studio/Content/Material Library/mesh_fence.shader
+++ b/Studio/Content/Material Library/mesh_fence.shader
@@ -69,6 +69,7 @@ struct layer_result
// temporary declarations
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
texture_return tmp4;
vec3 tmp5;
@@ -115,7 +116,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -140,7 +141,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -197,11 +198,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb );
- tmp5 = tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat );
- ftmp0 = tmp4.tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb );
+ tmp5 = tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat );
+ ftmp0 = tmp4.tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/metal_mesh_fine.shader b/Studio/Content/Material Library/metal_mesh_fine.shader
index f4e2d9f..b60b1a6 100644
--- a/Studio/Content/Material Library/metal_mesh_fine.shader
+++ b/Studio/Content/Material Library/metal_mesh_fine.shader
@@ -69,7 +69,9 @@ struct layer_result
// temporary declarations
+texture_coordinate_info tmp1;
texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
vec3 tmp4;
vec3 tmp6;
vec4 tmpShadowTerm;
@@ -114,7 +116,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp6, lightDir, lightDiffuse );
#endif
}
@@ -139,7 +141,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp6, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -186,7 +188,7 @@ float computeIOR()
float evalCutout()
{
- return( fileTexture(cutout_opacity_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono );
+ return( fileTexture(cutout_opacity_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono );
}
vec3 computeNormal()
@@ -196,10 +198,13 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_cutout_opacity_texture(texCoord0), tangent, binormal ) );
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmp6 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/paper_artistic.shader b/Studio/Content/Material Library/paper_artistic.shader
index 6c7b075..6c5c156 100644
--- a/Studio/Content/Material Library/paper_artistic.shader
+++ b/Studio/Content/Material Library/paper_artistic.shader
@@ -89,7 +89,9 @@ struct layer_result
// temporary declarations
+texture_coordinate_info tmp0;
texture_coordinate_info tmp1;
+texture_coordinate_info tmp3;
vec3 tmp2;
vec3 ftmp0;
vec4 tmpShadowTerm;
@@ -126,7 +128,7 @@ vec3 computeFrontMaterialEmissive()
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 )) ) );
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, lightDiffuse )) ) );
#endif
}
@@ -210,15 +212,18 @@ float evalCutout()
vec3 computeNormal()
{
- return( tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat ) );
+ return( tangentSpaceNormalTexture( bump_texture, bump_amount, false, false, tmp0, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat ) );
}
void computeTemporaries()
{
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp2 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint, 1.000000, color_layer_blend ) ), tmp2, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp0 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_transmission_texture(texCoord0), tangent, binormal ) );
+ tmp2 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint, 1.000000, color_layer_blend ) ), tmp2, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/paper_office.shader b/Studio/Content/Material Library/paper_office.shader
index 6f183a5..ec27c16 100644
--- a/Studio/Content/Material Library/paper_office.shader
+++ b/Studio/Content/Material Library/paper_office.shader
@@ -90,6 +90,7 @@ struct layer_result
// temporary declarations
texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
vec3 ftmp0;
vec4 tmpShadowTerm;
@@ -125,7 +126,7 @@ vec3 computeFrontMaterialEmissive()
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 )) ) );
+ layers[0].base += tmpShadowTerm * normalizedMix( bsdf_component[2]( bsdf_component(transmission_weight, diffuseTransmissionBSDF( -normal, lightDir, viewDir, lightDiffuse, vec4( ftmp0, 1.0), uTranslucentFalloff, uDiffuseLightWrap )) ,bsdf_component(reflection_weight, diffuseReflectionBSDF( normal, lightDir, lightDiffuse )) ) );
#endif
}
@@ -209,14 +210,16 @@ float evalCutout()
vec3 computeNormal()
{
- return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+ return( fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
}
void computeTemporaries()
{
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint, 0.700000, color_layer_blend ) ), paper_color.rgb, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.0);
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_transmission_texture(texCoord0), tangent, binormal ) );
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) );
+ ftmp0 = blendColorLayers( color_layer[1]( color_layer(blendColorLayers( color_layer[1]( color_layer(fileTexture(transmission_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp1, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint, 0.700000, color_layer_blend ) ), paper_color.rgb, mono_average ).tint, 1.000000, color_layer_multiply ) ), vec3( 1, 1, 1 ), mono_average ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/plastic_structured_red.shader b/Studio/Content/Material Library/plastic_structured_red.shader
index 1e6b798..9710d75 100644
--- a/Studio/Content/Material Library/plastic_structured_red.shader
+++ b/Studio/Content/Material Library/plastic_structured_red.shader
@@ -96,7 +96,7 @@ vec3 computeFrontMaterialEmissive()
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse);
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
#endif
@@ -119,7 +119,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
@@ -168,7 +168,7 @@ float evalCutout()
vec3 computeNormal()
{
- return( perlinNoiseBumpTexture( transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( ( texture_scaling*10.000000 ) ) ), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
+ return( perlinNoiseBumpTexture( scaleCoordinate(vec3(texture_scaling*10.000000), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
}
void computeTemporaries()
diff --git a/Studio/Content/Material Library/plastic_structured_red_emissive.shader b/Studio/Content/Material Library/plastic_structured_red_emissive.shader
index f85719e..ed2d7bb 100644
--- a/Studio/Content/Material Library/plastic_structured_red_emissive.shader
+++ b/Studio/Content/Material Library/plastic_structured_red_emissive.shader
@@ -78,6 +78,8 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
vec4 tmpShadowTerm;
layer_result layers[1];
@@ -114,13 +116,14 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity * ( emission_color.rgb * fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp1, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint
+ * fileTexture(emissive_mask_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp2, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
#endif
@@ -143,7 +146,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
@@ -192,12 +195,14 @@ float evalCutout()
vec3 computeNormal()
{
- return( perlinNoiseBumpTexture( transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( ( texture_scaling*10.000000 ) ) ), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
+ return( perlinNoiseBumpTexture( scaleCoordinate( vec3(texture_scaling*10.000000), coordinateSource(texture_coordinate_object, 0 ) ), bump_factor, 1.000000, false, false, 0.000000, 6, true, vec3( 0.000000, 0.000000, 0.000000 ), 0.070000, 0.300000, 1.000000, normal ) );
}
void computeTemporaries()
{
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp1 = textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal );
+ tmp2 = textureCoordinateInfo( texcoordTransformed_emissive_mask_texture(texCoord0), tangent, binormal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/porcelain.shader b/Studio/Content/Material Library/porcelain.shader
index 8b5978e..2f97720 100644
--- a/Studio/Content/Material Library/porcelain.shader
+++ b/Studio/Content/Material Library/porcelain.shader
@@ -73,7 +73,7 @@ vec3 computeFrontMaterialEmissive()
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
#endif
@@ -96,7 +96,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
diff --git a/Studio/Content/Material Library/powder_coat.shader b/Studio/Content/Material Library/powder_coat.shader
index c26fa04..7113d38 100644
--- a/Studio/Content/Material Library/powder_coat.shader
+++ b/Studio/Content/Material Library/powder_coat.shader
@@ -103,7 +103,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
#endif
}
@@ -128,7 +128,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -180,7 +180,7 @@ float evalCutout()
vec3 computeNormal()
{
- return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), texture_scaling ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+ return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, scaleCoordinate(texture_scaling, textureCoordinateInfo( texcoordTransformed_powdercoat_bump_texture(texCoord0), tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
}
void computeTemporaries()
diff --git a/Studio/Content/Material Library/powder_coat_emissive.shader b/Studio/Content/Material Library/powder_coat_emissive.shader
index 4056079..21f58a7 100644
--- a/Studio/Content/Material Library/powder_coat_emissive.shader
+++ b/Studio/Content/Material Library/powder_coat_emissive.shader
@@ -110,7 +110,7 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( ( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint * emission_color.rgb ) * intensity ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
@@ -119,7 +119,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
#endif
}
@@ -144,7 +144,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -214,12 +214,12 @@ float evalCutout()
vec3 computeNormal()
{
- return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), texture_scaling ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
+ return( fileBumpTexture(powdercoat_bump_texture, bump_factor, mono_average, scaleCoordinate(texture_scaling, textureCoordinateInfo(texcoordTransformed_powdercoat_bump_texture(texCoord0), tangent, binormal )), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal ) );
}
void computeTemporaries()
{
- tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
+ tmp3 = textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal );
ftmp0 = vec3( reflectivity );
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/rubber_studded_black.shader b/Studio/Content/Material Library/rubber_studded_black.shader
index a2af7d0..e8f5560 100644
--- a/Studio/Content/Material Library/rubber_studded_black.shader
+++ b/Studio/Content/Material Library/rubber_studded_black.shader
@@ -101,7 +101,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp4, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp4, lightDir, lightDiffuse );
#endif
}
@@ -126,7 +126,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp4, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -183,7 +183,7 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp4 = fileBumpTexture(bump_texture, bump_amount, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmp4 = fileBumpTexture(bump_texture, bump_amount, mono_average, scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ) ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
diff --git a/Studio/Content/Material Library/rubber_studded_emissive.shader b/Studio/Content/Material Library/rubber_studded_emissive.shader
index de45c93..5dfc75a 100644
--- a/Studio/Content/Material Library/rubber_studded_emissive.shader
+++ b/Studio/Content/Material Library/rubber_studded_emissive.shader
@@ -73,9 +73,10 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
vec3 tmp5;
-texture_coordinate_info tmp6;
vec4 tmpShadowTerm;
layer_result layers[2];
@@ -109,7 +110,8 @@ bool evalTwoSided()
vec3 computeFrontMaterialEmissive()
{
- return( vec3( 1.0, 1.0, 1.0) * vec3( vec3( ( intensity * ( emission_color.rgb * ( fileTexture(emissive_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp6, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint*fileTexture(emissive_mask_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_alpha, tmp6, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_default ).tint ) ) ) ) ) );
+ return intensity * emission_color.rgb * fileTexture(emissive_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp1, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint
+ * fileTexture(emissive_mask_texture, vec3(0.0), vec3(1.0), mono_alpha, tmp2, vec2(0.0, 1.0), vec2(0.0, 1.0), wrap_repeat, wrap_repeat, gamma_default ).tint;
}
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
@@ -118,7 +120,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -143,7 +145,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -200,10 +202,12 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = textureCoordinateInfo( texCoord0, tangent, binormal );
- tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), tmp3 ), vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- tmp6 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( 1.000000, 1.000000, 1.000000 ) ), tmp3 );
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ vec3 tiling = vec3( texture_tiling[0], texture_tiling[1], 1.000000 );
+ tmp1 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_emissive_texture(texCoord0), tangent, binormal ));
+ tmp2 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_emissive_mask_texture(texCoord0), tangent, binormal ));
+ tmp3 = scaleCoordinate(tiling, textureCoordinateInfo( texcoordTransformed_bump_texture(texCoord0), tangent, binormal ));
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/simple_glass.shader b/Studio/Content/Material Library/simple_glass.shader
index 09aa2c9..5da99ed 100644
--- a/Studio/Content/Material Library/simple_glass.shader
+++ b/Studio/Content/Material Library/simple_glass.shader
@@ -95,7 +95,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, 0.000000, 0.000000, scatter_reflect_transmit );
#else
- layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, 0.000000, 0.000000 );
+ layers[0].base += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, 0.000000 );
#endif
}
diff --git a/Studio/Content/Material Library/steel_milled_concentric.shader b/Studio/Content/Material Library/steel_milled_concentric.shader
index 3cf9585..4cad29e 100644
--- a/Studio/Content/Material Library/steel_milled_concentric.shader
+++ b/Studio/Content/Material Library/steel_milled_concentric.shader
@@ -75,6 +75,8 @@ struct texture_return
// temporary declarations
+texture_coordinate_info tmp1;
+texture_coordinate_info tmp2;
texture_coordinate_info tmp3;
texture_return tmp4;
anisotropy_return tmp5;
@@ -121,7 +123,7 @@ vec3 computeFrontMaterialEmissive()
void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
{
#if QT3DS_ENABLE_CG_LIGHTING
- layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDF( normal, lightDir, lightDiffuse );
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, ftmp0, ftmp1, scatter_reflect );
#endif
@@ -144,7 +146,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, ftmp0, ftmp1 );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, ftmp0 );
#endif
}
@@ -198,15 +200,16 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp3 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
- tmp5 = anisotropyConversion( tmp4.mono, anisotropy, fileTexture(anisotropy_rot_texture, vec3( -1, -1, -1 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
- ftmp0 = tmp5.roughness_u;
- ftmp1 = tmp5.roughness_v;
- ftmp2 = fileTexture(diffuse_texture, vec3( 1, 1, 1 ), vec3( -1, -1, -1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp3 = tmp5.tangent_u;
- ftmp4 = tmp4.tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp2 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_anisotropy_rot_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp4 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear );
+ tmp5 = anisotropyConversion( tmp4.mono, anisotropy, fileTexture(anisotropy_rot_texture, vec3( -1, -1, -1 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).mono, tangent, false );
+ ftmp0 = tmp5.roughness_u;
+ ftmp1 = tmp5.roughness_v;
+ ftmp2 = fileTexture(diffuse_texture, vec3( 1, 1, 1 ), vec3( -1, -1, -1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp3 = tmp5.tangent_u;
+ ftmp4 = tmp4.tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/thin_glass_frosted.shader b/Studio/Content/Material Library/thin_glass_frosted.shader
index b66c4cd..63b0c4e 100644
--- a/Studio/Content/Material Library/thin_glass_frosted.shader
+++ b/Studio/Content/Material Library/thin_glass_frosted.shader
@@ -152,7 +152,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
#else
- layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].base += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
@@ -212,10 +212,8 @@ vec3 computeNormal()
void computeTemporaries()
{
- //tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), refractCoords ), coordinateSource(texture_coordinate_world, 0 ) );
- //ftmp1 = perlinNoiseBumpTexture( tmp0, refractScale, 1.000000, false, false, 0.000000, 1, false, vec3( 0.000000, 0.000000, 0.000000 ), 1.0, 0.5, 1.000000, viewDir );
- tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), coordinateSource(texture_coordinate_world, 0 ) );
+ tmp0 = scaleCoordinate(bumpCoords, textureCoordinateInfo( texcoordTransformed_glass_bump(texCoord0), tangent, binormal ));
+ tmp1 = scaleCoordinate(bumpCoords, coordinateSource(texture_coordinate_world, 0 ));
ftmp1 = viewDir;
ftmp0 = vec3( reflectivity_amount );
tmpShadowTerm = evalBakedShadowMap( texCoord0 );
diff --git a/Studio/Content/Material Library/thin_glass_frosted_sp.shader b/Studio/Content/Material Library/thin_glass_frosted_sp.shader
index 6619ec2..8e4547a 100644
--- a/Studio/Content/Material Library/thin_glass_frosted_sp.shader
+++ b/Studio/Content/Material Library/thin_glass_frosted_sp.shader
@@ -135,7 +135,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
#else
- layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].base += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
@@ -190,10 +190,10 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp0 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), noiseCoords ), coordinateSource(texture_coordinate_world, 0 ) );
- tmp1 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), bumpCoords ), coordinateSource(texture_coordinate_world, 0 ) );
- ftmp0 = vec3( reflectivity_amount );
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp0 = scaleCoordinate(noiseCoords, coordinateSource(texture_coordinate_world, 0 ) );
+ tmp1 = scaleCoordinate(bumpCoords, coordinateSource(texture_coordinate_world, 0 ) );
+ ftmp0 = vec3( reflectivity_amount );
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/Studio/Content/Material Library/thin_glass_refractive.shader b/Studio/Content/Material Library/thin_glass_refractive.shader
index 16cf172..289b634 100644
--- a/Studio/Content/Material Library/thin_glass_refractive.shader
+++ b/Studio/Content/Material Library/thin_glass_refractive.shader
@@ -97,7 +97,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[0].base += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect_transmit );
#else
- layers[0].base += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].base += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
#endif
}
diff --git a/Studio/Content/Material Library/walnut_matte.shader b/Studio/Content/Material Library/walnut_matte.shader
index 4541241..e3b3ac4 100644
--- a/Studio/Content/Material Library/walnut_matte.shader
+++ b/Studio/Content/Material Library/walnut_matte.shader
@@ -70,6 +70,7 @@ struct texture_return
// temporary declarations
texture_coordinate_info tmp2;
+texture_coordinate_info tmp3;
vec3 tmp5;
vec3 ftmp0;
vec3 ftmp1;
@@ -115,7 +116,7 @@ void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir,
layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, viewDir, lightDiffuse, 0.000000 );
+ layers[1].layer += tmpShadowTerm * diffuseReflectionBSDF( tmp5, lightDir, lightDiffuse );
#endif
}
@@ -140,7 +141,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
layers[1].layer += tmpShadowTerm * diffuseReflectionBSDFEnvironment( tmp5, 0.000000 ) * aoFactor;
#else
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness );
layers[1].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
layers[1].layer += tmpShadowTerm * sampleDiffuse( layers[1].tanFrame ) * aoFactor;
@@ -197,11 +198,12 @@ vec3 computeNormal()
void computeTemporaries()
{
- tmp2 = transformCoordinate( rotationTranslationScale( vec3( 0.000000, 0.000000, 0.000000 ), vec3( 0.000000, 0.000000, 0.000000 ), vec3( texture_tiling[0], texture_tiling[1], 1.000000 ) ), textureCoordinateInfo( texCoord0, tangent, binormal ) );
- tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
- ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
- ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
- tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+ tmp2 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_reflect_texture(texCoord0), tangent, binormal ) );
+ tmp3 = scaleCoordinate(vec3( texture_tiling[0], texture_tiling[1], 1.000000 ), textureCoordinateInfo( texcoordTransformed_diffuse_texture(texCoord0), tangent, binormal ) );
+ tmp5 = fileBumpTexture(bump_texture, bump_amount, mono_average, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, normal );
+ ftmp0 = fileTexture(reflect_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp2, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_linear ).tint;
+ ftmp1 = fileTexture(diffuse_texture, vec3( 0, 0, 0 ), vec3( 1, 1, 1 ), mono_luminance, tmp3, vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 ), wrap_repeat, wrap_repeat, gamma_srgb ).tint;
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
}
vec4 computeLayerWeights( in float alpha )
diff --git a/commonplatform.pri b/commonplatform.pri
index 732d874..0caee32 100644
--- a/commonplatform.pri
+++ b/commonplatform.pri
@@ -23,6 +23,19 @@ DEFINES += \
# category e.g. with "QT_LOGGING_RULES=qt3ds.perf_info=true"
#DEFINES += QT3DS_ENABLE_PERF_LOGGING
+# Enable this to set the maximum amount of lights. The default value is 16.
+#DEFINES += QT3DS_MAX_NUM_LIGHTS=16
+
+# Enable this to set the maximum amount of shadows The default value is 8.
+#DEFINES += QT3DS_MAX_NUM_SHADOWS=8
+
+# Enable this to use legacy ASTC loading methods.
+#DEFINES += LEGACY_ASTC_LOADING
+
+# Enable this define if all ASTC images should be considered as premultiplied.
+# Alternatively to enable this at runtime, set QT3DS_ALL_ASTC_PREMULTIPLIED env variable.
+#DEFINES += QT3DS_ALL_ASTC_PREMULTIPLIED
+
win32: PlatformSpecificDir = windows
macos: PlatformSpecificDir = macos
linux|integrity|qnx: PlatformSpecificDir = linux
@@ -62,7 +75,6 @@ linux-clang {
macos {
DEFINES += _MACOSX _LINUXPLATFORM WIDE_IS_DIFFERENT_TYPE_THAN_CHAR16_T
- INCLUDEPATH += /usr/local/include
# macOS builds treat most warnings as errors to prevent slipping more warnings
# in to the code
@@ -262,7 +274,6 @@ clang {
android {
QMAKE_CXXFLAGS -= -fstack-protector-strong
QMAKE_CFLAGS -= -fstack-protector-strong
- INCLUDEPATH += $$(ANDROID_NDK_ROOT)/sysroot/usr/include
DEFINES += __BITS_PER_LONG=32
}
diff --git a/examples/studio3d/dynamicelement/presentation/materials/copper.shader b/examples/studio3d/dynamicelement/presentation/materials/copper.shader
index cf9e1ad..a2ebe8b 100644
--- a/examples/studio3d/dynamicelement/presentation/materials/copper.shader
+++ b/examples/studio3d/dynamicelement/presentation/materials/copper.shader
@@ -93,7 +93,7 @@ void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFact
#else
layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
- layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+ layers[0].layer += tmpShadowTerm * sampleGlossy( layers[0].tanFrame, viewDir, roughness);
#endif
}
diff --git a/examples/studio3d/simpleqml/main.qml b/examples/studio3d/simpleqml/main.qml
index abdcb79..4cbea83 100644
--- a/examples/studio3d/simpleqml/main.qml
+++ b/examples/studio3d/simpleqml/main.qml
@@ -77,7 +77,7 @@ Rectangle {
Presentation {
id: s3dpres
source: "qrc:/presentation/barrel.uia"
- onCustomSignalEmitted: customSignalName.text = Date.now() + ": " + name
+ onCustomSignalEmitted: customSignalName.text = Date.now() + ": customSignal:" + name
onSlideEntered: slideEnter.text = "Entered slide " + name + "(index " + index + ") on " + elementPath
onSlideExited: slideExit.text = "Exited slide " + name + "(index " + index + ") on " + elementPath
@@ -218,19 +218,19 @@ Rectangle {
id: customSignalName
anchors.bottom: parent.bottom
anchors.left: fpsCount.right
- anchors.leftMargin: 8
+ anchors.leftMargin: 30
}
Text {
id: slideEnter
anchors.bottom: parent.bottom
anchors.left: customSignalName.right
- anchors.leftMargin: 8
+ anchors.leftMargin: 30
}
Text {
id: slideExit
anchors.bottom: parent.bottom
anchors.left: slideEnter.right
- anchors.leftMargin: 8
+ anchors.leftMargin: 30
}
Button {
id: nextSlideByIndex
diff --git a/examples/studio3d/simpleqml/presentation/barrel.uip b/examples/studio3d/simpleqml/presentation/barrel.uip
index 7b9b2fb..c36f0e5 100644
--- a/examples/studio3d/simpleqml/presentation/barrel.uip
+++ b/examples/studio3d/simpleqml/presentation/barrel.uip
@@ -1,47 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<UIP version="6" >
<Project >
- <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" preferKtx="False" >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" preferKtx="False" flipCompressedTextures="False" >
<CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
</ProjectSettings>
+ <BufferData >
+ <ImageBuffer sourcepath="maps/barrel_barrel_Diffuse.png" hasTransparency="False" hasOpaquePixels="True" />
+ <ImageBuffer sourcepath="maps/barrel_barrel_Emissive.png" hasTransparency="False" hasOpaquePixels="True" />
+ <ImageBuffer sourcepath="maps/barrel_barrel_Normal.png" hasTransparency="False" hasOpaquePixels="True" />
+ <ImageBuffer sourcepath="maps/barrel_barrel_Specular.png" hasTransparency="False" hasOpaquePixels="True" />
+ </BufferData>
<Graph >
- <Scene id="Scene" >
- <Layer id="Layer" variants="" >
- <Camera id="Camera" />
- <Light id="Light" />
- <Model id="Barrel" variants="" >
- <Material id="Material" >
- <Image id="Material_diffusemap" />
- <Image id="Material_normalmap" />
- <Image id="Material_emissivemap" />
- <Image id="Material_specularmap" />
+ <Scene id="Scene_u51457" >
+ <Layer id="Layer_u16894" variants="" >
+ <Camera id="Camera_u20801" />
+ <Light id="Light_u60375" />
+ <Model id="Barrel_u17933" variants="" >
+ <Material id="Material_u43207" >
+ <Image id="Material_diffusemap_u25218" />
+ <Image id="Material_normalmap_u31730" />
+ <Image id="Material_emissivemap_u20392" />
+ <Image id="Material_specularmap_u63189" />
</Material>
</Model>
- <Text id="Text" variants="" />
- <Text id="Text2" variants="" />
+ <Text id="Text_u12278" variants="" />
+ <Text id="Text2_u28451" variants="" />
+ <Group id="Group_u19473" variants="" />
</Layer>
</Scene>
</Graph>
<Logic >
- <State name="Master Slide" component="#Scene" >
- <Add ref="#Layer" />
- <Add ref="#Camera" />
- <Add ref="#Light" />
- <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
- <Add ref="#Barrel" name="Barrel" position="0 -42 -483" rotation="90 0 0" scale="100 100 100" sourcepath=".\barrel\meshes\Barrel.mesh#1" >
+ <State name="Master Slide" component="#Scene_u51457" >
+ <Add ref="#Layer_u16894" />
+ <Add ref="#Camera_u20801" />
+ <Add ref="#Light_u60375" />
+ <State id="Scene-Slide1_u1119" name="Slide1" playmode="Looping" >
+ <Add ref="#Barrel_u17933" name="Barrel" position="0 -42 -483" rotation="90 0 0" scale="100 100 100" sourcepath=".\barrel\meshes\Barrel.mesh#1" >
<AnimationTrack property="opacity" type="EaseInOut" />
<AnimationTrack property="rotation.x" type="EaseInOut" >0 90 100 100 5 64 100 100 10 90 100 100</AnimationTrack>
<AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 5 -302 100 100 10 0 100 100</AnimationTrack>
<AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 5 0 100 100 10 0 100 100</AnimationTrack>
</Add>
- <Add ref="#Material" bumpamount="0" diffuse="1 1 1 1" diffusemap="#Material_diffusemap" emissivemap="#Material_emissivemap" fresnelPower="25" normalmap="#Material_normalmap" specularamount="4" specularmap="#Material_specularmap" specularmodel="Default" specularroughness="0.001" >
+ <Add ref="#Material_u43207" bumpamount="0" diffuse="1 1 1 1" diffusemap="#Material_diffusemap_u25218" emissivemap="#Material_emissivemap_u20392" fresnelPower="25" normalmap="#Material_normalmap_u31730" specularamount="4" specularmap="#Material_specularmap_u63189" specularmodel="Default" specularroughness="0.001" >
<AnimationTrack property="bumpamount" type="EaseInOut" >0 0 100 100 5 1 100 100</AnimationTrack>
</Add>
- <Add ref="#Material_diffusemap" sourcepath=".\maps\barrel_barrel_Diffuse.png" />
- <Add ref="#Material_normalmap" sourcepath=".\maps\barrel_barrel_Normal.png" />
- <Add ref="#Material_emissivemap" sourcepath=".\maps\barrel_barrel_Emissive.png" />
- <Add ref="#Material_specularmap" sourcepath=".\maps\barrel_barrel_Specular.png" />
- <Add ref="#Text" name="Text" font="Arimo-Regular" position="-486.418 297.128 50.5569" textcolor="0 1 0 1" textstring="Barrel!" tracking="0" >
+ <Add ref="#Material_diffusemap_u25218" sourcepath=".\maps\barrel_barrel_Diffuse.png" />
+ <Add ref="#Material_normalmap_u31730" sourcepath=".\maps\barrel_barrel_Normal.png" />
+ <Add ref="#Material_emissivemap_u20392" sourcepath=".\maps\barrel_barrel_Emissive.png" />
+ <Add ref="#Material_specularmap_u63189" sourcepath=".\maps\barrel_barrel_Specular.png" />
+ <Add ref="#Text_u12278" name="Text" font="Arimo-Regular" position="-486.418 297.128 50.5569" textcolor="0 1 0 1" textstring="Barrel!" tracking="0" >
<AnimationTrack property="opacity" type="EaseInOut" >0 100 100 100 5.009 43.75 100 100 10 100 100 100</AnimationTrack>
<AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 4.997 0 100 100 5.009 0 100 100 10 0 100 100</AnimationTrack>
<AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 4.997 0 100 100 5.009 0 100 100 10 360 100 100</AnimationTrack>
@@ -50,7 +57,15 @@
<AnimationTrack property="textcolor.y" type="EaseInOut" >0 1 100 100 5.009 0.235294 100 100 10 1 100 100</AnimationTrack>
<AnimationTrack property="textcolor.z" type="EaseInOut" >0 0 100 100 5.009 0.333333 100 100 10 0 100 100</AnimationTrack>
</Add>
- <Add ref="#Text2" name="Text2" controlledproperty="$di_text textstring" font="Arimo-Regular" position="437.342 256.921 0" />
+ <Add ref="#Text2_u28451" name="Text2" controlledproperty="$di_text textstring" font="Arimo-Regular" position="437.342 256.921 0" />
+ <Add ref="#Group_u19473" name="Group" endtime="3083" starttime="1433" >
+ <Action id="Group-Action_u35574" eyeball="True" triggerObject="#Group_u19473" event="onActivate" targetObject="#Group_u19473" handler="Emit Signal" >
+ <HandlerArgument name="Signal Name" type="String" argtype="Signal" value="CustomTestSignal1" />
+ </Action>
+ <Action id="Group-Action_u20930" eyeball="True" triggerObject="#Group_u19473" event="onDeactivate" targetObject="#Group_u19473" handler="Emit Signal" >
+ <HandlerArgument name="Signal Name" type="String" argtype="Signal" />
+ </Action>
+ </Add>
</State>
</State>
</Logic>
diff --git a/ogl-runtime.pro b/ogl-runtime.pro
index 44d9fd6..0e399c3 100644
--- a/ogl-runtime.pro
+++ b/ogl-runtime.pro
@@ -8,7 +8,7 @@ integrity {
CHECK_INTEGRITY_DIR = $$(INTEGRITY_DIR)
}
-ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$) {
+ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$)|contains(QMAKE_HOST.arch, mips64)|contains(QT_ARCH, mips64) {
message("WARNING, target not supported by ogl-runtime")
#Exclude non-working cross-compile targets, see:
# QT3DS-3647 ogl-runtime doesn't compile on TvOS_ANY in CI
@@ -16,6 +16,7 @@ ios|tvos|watchos|winrt|wasm|*-icc*|contains(CHECK_INTEGRITY_DIR, .*int1144$) {
# QT3DS-3646 ogl-runtime doesn't compile on IOS_ANY in CI
# QT3DS-3649 ogl-runtime doesn't compile on WinRT in CI
# QT3DS-3650 ogl-runtime doesn't compile on WebAssembly in CI
+ # QT3DS-4129 ogl-runtime doesn't compile on Qemu mips64 in CI
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += src_dummy
diff --git a/product_dependencies.yaml b/product_dependencies.yaml
new file mode 100644
index 0000000..fa5342c
--- /dev/null
+++ b/product_dependencies.yaml
@@ -0,0 +1,3 @@
+dependencies:
+ ../../qt/tqtc-qt5.git:
+ ref: "tqtc/lts-5.15"
diff --git a/res.qrc b/res.qrc
index c5c59b2..cc7232f 100644
--- a/res.qrc
+++ b/res.qrc
@@ -60,7 +60,7 @@
<file>res/effectlib/sampleArea.glsllib</file>
<file>res/effectlib/funcsampleLightVars.glsllib</file>
<file>res/effectlib/sampleLight.glsllib</file>
- <file>res/effectlib/sampleProbe.glsllib</file>
+ <file>res/effectlib/sampleProbePre.glsllib</file>
<file>res/effectlib/screenSpaceAO.glsllib</file>
<file>res/effectlib/screenSpaceDO.glsllib</file>
<file>res/effectlib/shadowMapping.glsllib</file>
@@ -90,7 +90,7 @@
<file>res/effectlib/weightedLayer.glsllib</file>
<file>res/effectlib/wireframeCM.glsllib</file>
<file>res/effectlib/gles2/funcsampleLightVars.glsllib</file>
- <file>res/effectlib/gles2/sampleProbe.glsllib</file>
+ <file>res/effectlib/gles2/sampleProbePre.glsllib</file>
<file>res/effectlib/gles2/SSAOCustomMaterial.glsllib</file>
<file>res/effectlib/gles2/funcareaLightVars.glsllib</file>
<file>res/effectlib/gles2/monoChannel.glsllib</file>
@@ -113,5 +113,7 @@
<file>res/effectlib/distancefieldtext_dropshadow.vert</file>
<file>res/effectlib/distancefieldtext_dropshadow_core.frag</file>
<file>res/effectlib/distancefieldtext_dropshadow_core.vert</file>
+ <file>res/effectlib/funcsampleNormalTexture.glsllib</file>
+ <file>res/effectlib/sampleProbe.glsllib</file>
</qresource>
</RCC>
diff --git a/res/DataModelMetadata/en-us/MetaData.xml b/res/DataModelMetadata/en-us/MetaData.xml
index e249d22..acb6e68 100644
--- a/res/DataModelMetadata/en-us/MetaData.xml
+++ b/res/DataModelMetadata/en-us/MetaData.xml
@@ -49,6 +49,8 @@
<Event name="onPressureDown" category="Gesture" />
<Event name="onPressureUp" category="Gesture" />
<Event name="onTap" category="Gesture" />
+ <Event name="onActivate" category="Time" />
+ <Event name="onDeactivate" category="Time" />
<!--
<Event name="onDoubleTap" category="Gesture" />
<Event name="onSingleTap" category="Gesture" />
@@ -126,6 +128,8 @@
<Property name="positionv" formalName="V Position" description="Offset of the image along the V\ndirection of the material" />
<Property name="pivotu" formalName="U Pivot" description="Offset the image in the U direction\nwithout affecting rotation center" />
<Property name="pivotv" formalName="V Pivot" description="Offset the image in the V direction\nwithout affecting rotation center" />
+ <Property name="minfilter" formalName="Minification Filter" default="Linear" description="The minification filter of the image" list="Nearest:Linear:NearestMipmapNearest:NearestMipmapLinear:LinearMipmapNearest:LinearMipmapLinear" />
+ <Property name="magfilter" formalName="Magnification Filter" default="Linear" description="The magnification filter of the image" list="Nearest:Linear" />
<!-- Texture subpresentation is not set to controllable as it does not currently work in runtime -->
<Property name="subpresentation" formalName="Sub-Presentation" description="Presentation or QML stream\nto use instead of the image" type="Renderable" />
@@ -154,6 +158,7 @@
<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="cullmode" formalName="Culling Mode" default="Back" category="Material" description="Disable drawing of polygons facing certain direction." list="Back:Front:All:None" />
<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" />
@@ -227,6 +232,8 @@
</Component>
<Group>
+ <!-- Basic Properties -->
+ <Property name="ordered" formalName="Ordered" type="Boolean" default="False" category="Basic Properties" description="The group is ordered. Draw objects in the group order (disables dynamic depth sorting). " />
<!-- Variant Tags -->
<Property name="variants" type="String" animatable="False" category="Variant Tags" />
@@ -304,9 +311,22 @@
<ShowIfEqual property="vertfields" value="Top/Bottom"/>
<ShowIfEqual property="vertfields" value="Height/Bottom"/>
</Property>
+ <Property name="dynamicresize" formalName="Dynamic Resize" description="Resize the layer dynamically\nbased on the content" type="Boolean" default="False" category="Size" />
+ <Property name="dynamicpadding" formalName="Padding" description="Pad the resized layer to prevent constant\nresizing when small changes are made." min="0" default="0" animatable="False" category="Size">
+ <ShowIfEqual property="dynamicresize" value="True"/>
+ </Property>
+ <Property name="dynamicpaddingunits" formalName="Padding Units" description="Padding is percent of overall\nwidth or absolute pixels" list="percent:pixels" default="percent" category="Size">
+ <ShowIfEqual property="dynamicresize" value="True"/>
+ </Property>
+ <Property name="dynamiccombine" formalName="Combine Bounds" description="Combine layer object bounds for faster\ncalculation, but lower accuracy." type="Boolean" default="False" category="Size">
+ <ShowIfEqual property="dynamicresize" value="True"/>
+ </Property>
<!-- Ambient Occlusion -->
- <Property name="aostrength" formalName="Ambient Occlusion" description="Amount of ambient occlusion shading\nto apply" min="0" max="100" default="0" category="Ambient Occlusion" >
+ <Property name="aoenabled" formalName="Ambient Occlusion" description="Use ambient occlusion" type="Boolean" default="False" category="Ambient Occlusion">
+ <ShowIfEqual property="sourcepath" value=""/>
+ </Property>
+ <Property name="aostrength" formalName="AO Strength" description="Amount of ambient occlusion shading\nto apply" min="0" max="100" default="0" category="Ambient Occlusion" >
<ShowIfEqual property="sourcepath" value=""/>
</Property>
<Property name="aodistance" formalName="AO Distance" description="Size of the ambient occlusion shading" default="5" category="Ambient Occlusion">
@@ -445,7 +465,7 @@
<!-- Format -->
<Property name="textstring" formalName="Text String" type="MultiLineString" default="Text" category="Format" description="Text String" controllable="True" />
<Property name="textcolor" formalName="Text Color" type="Color" default="1 1 1 1" category="Format" description="Text Color" controllable="True" />
- <Property name="font" formalName="Font" type="Font" default="TitilliumWeb-Regular" category="Format" description="Font" />
+ <Property name="font" formalName="Font" type="Font" default="TitilliumWeb-Regular" category="Format" description="Font" controllable="True" />
<!-- HW accelerated fonts not supported
<Property name="enableacceleratedfont" formalName="Hardware accelerated font" description="Enabled hardware acclerated font" type="Boolean" default="false" category="Format" />
-->
diff --git a/res/effectlib/customMaterial.glsllib b/res/effectlib/customMaterial.glsllib
index 0a4d88b..d6f392e 100644
--- a/res/effectlib/customMaterial.glsllib
+++ b/res/effectlib/customMaterial.glsllib
@@ -31,9 +31,6 @@
#ifndef CUSTOM_MATERIAL_GLSLLIB
#define CUSTOM_MATERIAL_GLSLLIB 1
-#define SNAPPER_SAMPLER2D(samplerName, samplerNiceName, texFilter, texWrap, showUI )\
-uniform sampler2D samplerName;
-
// some useful defines
#ifndef PI
#define PI 3.14159265358979
diff --git a/res/effectlib/defaultMaterialFresnel.glsllib b/res/effectlib/defaultMaterialFresnel.glsllib
index e0eff4f..7a363e9 100644
--- a/res/effectlib/defaultMaterialFresnel.glsllib
+++ b/res/effectlib/defaultMaterialFresnel.glsllib
@@ -31,13 +31,11 @@
#ifndef DEFAULT_MATERIAL_FRESNEL_GLSLLIB
#define DEFAULT_MATERIAL_FRESNEL_GLSLLIB
-float defaultMaterialSimpleFresnel( in vec3 N, in vec3 viewDir, in float ior, float fresnelPower )
+float defaultMaterialSimpleFresnel(in vec3 N, in vec3 viewDir, in float ior, float fresnelPower)
{
float F = ((1.0-ior) * (1.0-ior)) / ((1.0+ior) * (1.0+ior));
- float VdotN = dot(viewDir, N);
- VdotN = clamp( VdotN, 0.0, 1.0 );
+ float VdotN = max(dot(viewDir, N), 0.0);
float ratio = F + (1.0 - F) * pow(1.0 - VdotN, fresnelPower);
-
return ratio;
}
diff --git a/res/effectlib/distancefieldtext.frag b/res/effectlib/distancefieldtext.frag
index 1d83490..2236f9c 100644
--- a/res/effectlib/distancefieldtext.frag
+++ b/res/effectlib/distancefieldtext.frag
@@ -20,8 +20,8 @@ void main()
#ifdef use_fallback
highp float alpha = smoothstep(alphas.x, alphas.y, distance);
#else
- highp float f = fwidth(distance);
- highp float alpha = smoothstep(0.5 - f, 0.5, distance);
+ highp float f = fwidth(distance) * 0.5;
+ highp float alpha = smoothstep(0.5 - f, 0.5 + f, distance);
#endif
gl_FragColor = color * alpha;
diff --git a/res/effectlib/distancefieldtext_core.frag b/res/effectlib/distancefieldtext_core.frag
index f11dcc1..a3a25a2 100644
--- a/res/effectlib/distancefieldtext_core.frag
+++ b/res/effectlib/distancefieldtext_core.frag
@@ -6,6 +6,6 @@ uniform vec4 color;
void main()
{
float distance = texture(_qt_texture, sampleCoord).r;
- float f = fwidth(distance);
- fragOutput = color * smoothstep(0.5 - f, 0.5, distance);
+ float f = fwidth(distance) * 0.5;
+ fragOutput = color * smoothstep(0.5 - f, 0.5 + f, distance);
}
diff --git a/res/effectlib/distancefieldtext_dropshadow.frag b/res/effectlib/distancefieldtext_dropshadow.frag
index fdb68ba..2f6c9be 100644
--- a/res/effectlib/distancefieldtext_dropshadow.frag
+++ b/res/effectlib/distancefieldtext_dropshadow.frag
@@ -25,8 +25,8 @@ void main()
#ifdef use_fallback
highp float shadowAlpha = smoothstep(alphas.x, alphas.y, shadowDistance);
#else
- highp float shadowDistanceD = fwidth(shadowDistance);
- highp float shadowAlpha = smoothstep(0.5 - shadowDistanceD, 0.5, shadowDistance);
+ highp float shadowDistanceD = fwidth(shadowDistance) * 0.5;
+ highp float shadowAlpha = smoothstep(0.5 - shadowDistanceD, 0.5 + shadowDistanceD, shadowDistance);
#endif
highp vec4 shadowPixel = color * shadowColor * shadowAlpha;
@@ -38,8 +38,8 @@ void main()
#ifdef use_fallback
highp float textAlpha = smoothstep(alphas.x, alphas.y, textDistance);
#else
- highp float textDistanceD = fwidth(textDistance);
- highp float textAlpha = smoothstep(0.5 - textDistanceD, 0.5, textDistance);
+ highp float textDistanceD = fwidth(textDistance) * 0.5;
+ highp float textAlpha = smoothstep(0.5 - textDistanceD, 0.5 + textDistanceD, textDistance);
#endif
highp vec4 textPixel = color * textAlpha;
diff --git a/res/effectlib/distancefieldtext_dropshadow_core.frag b/res/effectlib/distancefieldtext_dropshadow_core.frag
index e13182e..8e8c61d 100644
--- a/res/effectlib/distancefieldtext_dropshadow_core.frag
+++ b/res/effectlib/distancefieldtext_dropshadow_core.frag
@@ -12,16 +12,16 @@ void main()
clamp(shadowSampleCoord,
normalizedTextureBounds.xy,
normalizedTextureBounds.zw)).r;
- float shadowDistanceD = fwidth(shadowDistance);
- float shadowAlpha = smoothstep(0.5 - shadowDistanceD, 0.5, shadowDistance);
+ float shadowDistanceD = fwidth(shadowDistance) * 0.5;
+ float shadowAlpha = smoothstep(0.5 - shadowDistanceD, 0.5 + shadowDistanceD, shadowDistance);
vec4 shadowPixel = color * shadowColor * shadowAlpha;
float textDistance = texture(_qt_texture,
clamp(sampleCoord,
normalizedTextureBounds.xy,
normalizedTextureBounds.zw)).r;
- float textDistanceD = fwidth(textDistance);
- float textAlpha = smoothstep(0.5 - textDistanceD, 0.5, textDistance);
+ float textDistanceD = fwidth(textDistance) * 0.5;
+ float textAlpha = smoothstep(0.5 - textDistanceD, 0.5 + textDistanceD, textDistance);
vec4 textPixel = color * textAlpha;
fragOutput = mix(shadowPixel, textPixel, textPixel.a);
diff --git a/res/effectlib/evalBakedShadowMap.glsllib b/res/effectlib/evalBakedShadowMap.glsllib
index a283d8a..7ea3887 100644
--- a/res/effectlib/evalBakedShadowMap.glsllib
+++ b/res/effectlib/evalBakedShadowMap.glsllib
@@ -30,7 +30,7 @@
vec4 evalBakedShadowMap( in vec3 inCoords )
{
- vec4 shadowCol = (uShadowMappingEnabled) ? texture( uBakedShadowTexture, inCoords.xy ) : vec4( 1.0, 1.0, 1.0, 1.0 );
+ vec4 shadowCol = (uShadowMappingEnabled) ? texture( uBakedShadowTexture, texcoordTransformed_uBakedShadowTexture(inCoords).xy ) : vec4( 1.0, 1.0, 1.0, 1.0 );
return shadowCol;
}
diff --git a/res/effectlib/funcdiffuseReflectionBSDF.glsllib b/res/effectlib/funcdiffuseReflectionBSDF.glsllib
index bda0ea6..05f54a6 100644
--- a/res/effectlib/funcdiffuseReflectionBSDF.glsllib
+++ b/res/effectlib/funcdiffuseReflectionBSDF.glsllib
@@ -3,41 +3,8 @@
#define PI_SQUARE ( PI * PI )
#endif
-vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir,
- in vec3 lightDiffuse, in float roughness)
+vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 lightDiffuse)
{
- float cosThetaI = max( 0.0, dot( N, L ) );
- float factor = cosThetaI;
- if ( ( 0.0 < factor ) && ( 0.0 < roughness ) )
- {
- // see http://en.wikipedia.org/wiki/Oren%E2%80%93Nayar_reflectance_model
- float sigmaSquare = 0.25 * PI_SQUARE * roughness * roughness;
- float A = 1.0 - 0.5 * sigmaSquare / ( sigmaSquare + 0.33 );
- float B = 0.45 * sigmaSquare / ( sigmaSquare + 0.09 );
-
- // project L and viewDir on surface to get the azimuthal angle between them
- // as we don't really need the projections, but the angle between them,
- // it's enough to just use the cross instead
- vec3 pl = normalize( cross( L, N ) );
- vec3 pv = normalize( cross( viewDir, N ) );
- float cosPhi = max( 0.0, dot( pl, pv ) );
-
- float sinAlpha, tanBeta;
- float cosThetaO = max( 0.0, dot( N, viewDir ) );
- float sinThetaI = sqrt( max( 0.0, 1.0 - cosThetaI * cosThetaI ) );
- float sinThetaO = sqrt( max( 0.0, 1.0 - cosThetaO * cosThetaO ) );
- if ( cosThetaI < cosThetaO )
- { // -> thetaO < thetaI
- sinAlpha = sinThetaI;
- tanBeta = sinThetaO / cosThetaO;
- }
- else
- {
- sinAlpha = sinThetaO;
- tanBeta = sinThetaI / cosThetaI;
- }
-
- factor *= A + B * cosPhi * sinAlpha * tanBeta;
- }
- return( vec4( factor * lightDiffuse, 1.0 ) );
+ float factor = max(0.0, dot(N, L));
+ return vec4(factor * lightDiffuse, 1.0);
}
diff --git a/res/effectlib/funcsampleAreaGlossyDefault.glsllib b/res/effectlib/funcsampleAreaGlossyDefault.glsllib
index cb9cba1..586c693 100644
--- a/res/effectlib/funcsampleAreaGlossyDefault.glsllib
+++ b/res/effectlib/funcsampleAreaGlossyDefault.glsllib
@@ -1,25 +1,26 @@
#include "funccomputeMicroHit.glsllib"
-vec3 sampleAreaGlossyDefault( in mat3 tanFrame, in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 viewDir, in float roughU, in float roughV )
+vec3 sampleAreaGlossyDefault(in mat3 tanFrame, in vec3 pos, in mat3 lightFrame, in vec3 lightPos,
+ in float width, in float height, in vec3 viewDir, in float roughness)
{
- float sigmaU = clamp( 0.5 * roughU, 0.005, 0.5 );
- float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 );
+ float sigma = clamp(0.5 * roughness, 0.005, 0.5);
vec2 UVset[5];
- float thetaI = acos( dot(viewDir, lightFrame[2]) );
- vec2 minMaxThetaH = vec2( (thetaI - 1.5707) * 0.5,
- (thetaI + 1.5707) * 0.5 );
- vec4 sinCosThetaH = vec4( abs(sin(minMaxThetaH)), abs(cos(minMaxThetaH)) );
+ float thetaI = acos(dot(viewDir, lightFrame[2]));
+ vec2 minMaxThetaH = vec2((thetaI - 1.5707) * 0.5, (thetaI + 1.5707) * 0.5 );
+ vec4 sinCosThetaH = vec4(abs(sin(minMaxThetaH)), abs(cos(minMaxThetaH)));
// First thing we do is compute a small-scale version of the ray hit for a very tiny roughness
// then we scale that up based on the _actual_ roughness.
- float wt = computeMicroHit( pos, tanFrame, lightPos, lightFrame, width, height, viewDir, UVset );
+ float wt = computeMicroHit(pos, tanFrame, lightPos, lightFrame, width, height, viewDir, UVset);
UVset[0] -= UVset[4]; UVset[1] -= UVset[4];
UVset[2] -= UVset[4]; UVset[3] -= UVset[4];
- UVset[0] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaU); UVset[1] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaU);
- UVset[2] *= mix(1.0, sinCosThetaH.y / 0.005, sigmaV); UVset[3] *= mix(1.0, sinCosThetaH.x / 0.005, sigmaV);
+ UVset[0] *= mix(1.0, sinCosThetaH.y / 0.005, sigma);
+ UVset[1] *= mix(1.0, sinCosThetaH.x / 0.005, sigma);
+ UVset[2] *= mix(1.0, sinCosThetaH.y / 0.005, sigma);
+ UVset[3] *= mix(1.0, sinCosThetaH.x / 0.005, sigma);
UVset[0] += UVset[4]; UVset[1] += UVset[4];
UVset[2] += UVset[4]; UVset[3] += UVset[4];
@@ -31,12 +32,12 @@ vec3 sampleAreaGlossyDefault( in mat3 tanFrame, in vec3 pos, in mat3 lightFrame,
UVmin = min(UVmin, UVset[2]); UVmax = max(UVmax, UVset[2]);
UVmin = min(UVmin, UVset[3]); UVmax = max(UVmax, UVset[3]);
- cminUV = clamp( UVmin, vec2(0.0), vec2(1.0) );
- cmaxUV = clamp( UVmax, vec2(0.0), vec2(1.0) );
+ cminUV = clamp(UVmin, vec2(0.0), vec2(1.0));
+ cmaxUV = clamp(UVmax, vec2(0.0), vec2(1.0));
vec2 hitScale = (cmaxUV - cminUV);
vec2 fullScale = (UVmax - UVmin);
- float intensity = ( hitScale.x * hitScale.y ) / max( fullScale.x * fullScale.y, 0.0001 );
+ float intensity = (hitScale.x * hitScale.y) / max(fullScale.x * fullScale.y, 0.0001);
- return vec3( wt * intensity );
+ return vec3(wt * intensity);
}
diff --git a/res/effectlib/funcsampleNormalTexture.glsllib b/res/effectlib/funcsampleNormalTexture.glsllib
new file mode 100644
index 0000000..552112a
--- /dev/null
+++ b/res/effectlib/funcsampleNormalTexture.glsllib
@@ -0,0 +1,6 @@
+vec3 sampleNormalTexture(in sampler2D sampler, in float factor, in vec2 texCoord, in vec3 tangent,
+ in vec3 binormal, in vec3 normal)
+{
+ vec3 tsNormal = 2.0 * texture(sampler, texCoord).xyz - 1.0;
+ return mix(normal, normalize(tsNormal.x * tangent - tsNormal.y * binormal + tsNormal.z * normal), factor);
+}
diff --git a/res/effectlib/funcspecularBSDF.glsllib b/res/effectlib/funcspecularBSDF.glsllib
index e9450bf..f774b0b 100644
--- a/res/effectlib/funcspecularBSDF.glsllib
+++ b/res/effectlib/funcspecularBSDF.glsllib
@@ -6,37 +6,15 @@
#define scatter_reflect_transmit 2
#endif
-vec4 specularBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightSpecular,
- in float ior, in float shininess, in vec3 tint, int mode)
+vec4 specularBSDF(in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightSpecular, in float shininess)
{
- vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
- float cosTheta = dot( N, L );
- if ( 0.0 < cosTheta )
- {
- if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
- {
- vec3 R = reflect( -L, N );
- float cosAlpha = max( 0.0, dot( R, viewDir ) );
- float shine = pow( cosAlpha, shininess );
- rgba.rgb = shine * lightSpecular;
- }
+ vec4 rgba = vec4(0.0, 0.0, 0.0, 1.0);
+ float cosTheta = dot(N, L);
+ if (0.0 < cosTheta) {
+ vec3 R = reflect(-L, N);
+ float cosAlpha = max(0.0, dot(R, viewDir));
+ float shine = pow(cosAlpha, shininess);
+ rgba.rgb = shine * lightSpecular;
}
- if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
- {
- // check against total reflection
- vec3 R = refract( -viewDir, N, ior );
- if ( R == vec3( 0.0, 0.0, 0.0 ) )
- {
- rgba.a = 1.0;
- }
- else if ( mode == scatter_transmit )
- {
- rgba.a = 0.0;
- }
- else
- {
- rgba.a = 1.0 - luminance( tint );
- }
- }
- return( rgba );
+ return rgba;
}
diff --git a/res/effectlib/gles2/sampleProbe.glsllib b/res/effectlib/gles2/sampleProbe.glsllib
deleted file mode 100644
index f785918..0000000
--- a/res/effectlib/gles2/sampleProbe.glsllib
+++ /dev/null
@@ -1,482 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef SAMPLE_PROBE_GLSLLIB
-#define SAMPLE_PROBE_GLSLLIB 1
-
-#ifndef QT3DS_ENABLE_LIGHT_PROBE_2
-#define QT3DS_ENABLE_LIGHT_PROBE_2 0
-#endif
-
-#ifndef QT3DS_ENABLE_IBL_FOV
-#define QT3DS_ENABLE_IBL_FOV 0
-#endif
-
-uniform sampler2D light_probe;
-uniform vec4 light_probe_props;
-uniform vec4 light_probe_rotation;
-uniform vec4 light_probe_offset; // light_probe_offset.w = number of mipmaps
-uniform vec2 light_probe_size;
-
-#if QT3DS_ENABLE_LIGHT_PROBE_2
-uniform sampler2D light_probe2;
-uniform vec4 light_probe2_props;
-uniform vec2 light_probe2_size;
-#endif
-
-#if QT3DS_ENABLE_IBL_FOV
-uniform vec4 light_probe_opts;
-#endif
-
-float noise1d(vec2 n)
-{
- return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
-}
-
-mat3 orthoNormalize( in mat3 tanFrame )
-{
- mat3 outMat;
- outMat[0] = normalize( cross( tanFrame[1], tanFrame[2] ) );
- outMat[1] = normalize( cross( tanFrame[2], outMat[0] ) );
- outMat[2] = tanFrame[2];
-
- return outMat;
-}
-
-mat3 tangentFrame( vec3 N, vec3 p )
-{
- // get edge vectors of the pixel triangle
- vec3 dp1 = dFdx( p );
- vec3 dp2 = dFdy( p );
- // Using dPdu and dPdv would be nicer, but the nature of our materials
- // are not ones with intrinsic UVs, so we can't really go there.
-// vec2 duv1 = dFdx( uv );
-// vec2 duv2 = dFdy( uv );
-
- // solve the linear system
- vec3 dp2perp = cross( dp2, N );
- vec3 dp1perp = cross( N, dp1 );
-// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
-// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
-
- vec3 T = normalize(dp1perp);
- vec3 B = normalize(dp2perp);
- return mat3( T , B , N );
-}
-
-vec2 transformSample( vec2 origUV, vec4 probeRot, vec2 probeOfs )
-{
- vec2 retUV;
- retUV.x = dot( vec3(origUV, 1.0), vec3(probeRot.xy, probeOfs.x) );
- retUV.y = dot( vec3(origUV, 1.0), vec3(probeRot.zw, probeOfs.y) );
- return retUV;
-}
-
-// This is broken out into its own routine so that if we get some other
-// format image than a lat-long, then we can account for that by changing
-// the code here alone.
-vec2 getProbeSampleUV( vec3 smpDir, vec4 probeRot, vec2 probeOfs )
-{
- vec2 smpUV;
-
-#if QT3DS_ENABLE_IBL_FOV
- smpUV.x = (2.0 * atan(-smpDir.z, smpDir.x) + 3.14159265358 ) / light_probe_opts.x;
- smpUV.y = (2.0 * atan(-smpDir.z, smpDir.y) + 3.14159265358 ) / light_probe_opts.x;
-#else
- smpUV.x = atan( smpDir.x, -smpDir.z) / 3.14159265359;
- smpUV.y = 1.0 - (acos(smpDir.y) / 1.57079632679);
-#endif
- smpUV = transformSample( smpUV.xy * 0.5, probeRot, probeOfs ) + vec2(0.5, 0.5);
-
- return smpUV;
-}
-
-vec4 getTopLayerSample( vec3 inDir, float lodShift, vec3 lodOffsets )
-{
-#if QT3DS_ENABLE_LIGHT_PROBE_2
- if ( light_probe2_props.w < 0.5 )
- return vec4(0.0, 0.0, 0.0, 0.0);
-
- vec2 smpUV = getProbeSampleUV( inDir, vec4(1.0, 0.0, 0.0, 1.0), light_probe_props.xy );
- smpUV.x -= 0.5;
- smpUV.x *= light_probe2_props.x;
- smpUV.x += light_probe2_props.y;
-
- vec4 retVal = 0.4 * textureLod( light_probe2, smpUV , lodShift );
- retVal += 0.2 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.x );
- retVal += 0.3 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.y );
- retVal += 0.1 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.z );
- return retVal;
-#else
- return vec4(0.0, 0.0, 0.0, 0.0);
-#endif
-}
-
-vec3 getProbeSample( vec3 smpDir, float lodShift, vec3 normal )
-{
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
- return textureLod( light_probe, smpUV , lodShift ).xyz;
-}
-
-vec3 getProbeWeightedSample( vec3 smpDir, float lodShift, float roughness, vec3 normal )
-{
- // This gives us a weighted sum that approximates the total filter support
- // of the full-blown convolution.
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
- float wt = 1.0;
-
-#if QT3DS_ENABLE_IBL_FOV
- wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.x));
- wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.y));
- wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.x));
- wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.y));
-#endif
-
- vec3 lodOffsets;
- lodOffsets.x = mix(-2.0, -0.70710678, roughness);
- lodOffsets.y = min( 2.0 * smoothstep(0.0, 0.1, roughness), 2.0 - 1.29289 * smoothstep(0.1, 1.0, roughness) );
- lodOffsets.z = min( 6.0 * smoothstep(0.0, 0.1, roughness), 6.0 - 4.585786 * smoothstep(0.1, 1.0, roughness) );
-
- ivec2 iSize = ivec2(light_probe_size);
- vec3 ddx = dFdx( smpDir ) * float(iSize.x);
- vec3 ddy = dFdy( smpDir ) * float(iSize.y);
-// vec2 ddxUV = dFdx( smpUV ) * float(iSize.x);
-// vec2 ddyUV = dFdy( smpUV ) * float(iSize.y);
-
- vec2 deriv;
- deriv.x = max( dot(ddx, ddx), dot(ddy, ddy) );
-// deriv.y = max( dot(ddxUV, ddxUV), dot(ddyUV, ddyUV) );
- deriv = clamp( deriv, vec2(1.0), vec2(iSize.x * iSize.y) );
- vec2 lodBound = 0.5 * log2( deriv ) - vec2(1.0);
-
-// float minLod = 0.5 * (lodBound.x + lodBound.y);
- float minLod = lodBound.x;
- float maxLod = log2( max(float(iSize.x), float(iSize.y)) );
- minLod = clamp( minLod / maxLod, 0.0, 1.0 );
- minLod *= minLod * maxLod;
-
- lodShift = max( lodShift, minLod );
-
- vec3 retVal = 0.4 * textureLod( light_probe, smpUV , lodShift ).xyz;
- retVal += 0.2 * textureLod( light_probe, smpUV , max(minLod, lodShift+lodOffsets.x) ).xyz;
- retVal += 0.3 * textureLod( light_probe, smpUV , lodShift+lodOffsets.y ).xyz;
- retVal += 0.1 * textureLod( light_probe, smpUV , lodShift+lodOffsets.z ).xyz;
-
-#if QT3DS_ENABLE_LIGHT_PROBE_2
- vec4 topSmp = getTopLayerSample( smpDir, lodShift, lodOffsets );
- vec3 tempVal = mix( retVal, topSmp.xyz, topSmp.w );
- retVal = mix( retVal, tempVal, light_probe2_props.z );
-#endif
-
- if (light_probe_props.z > -1.0) {
- float ctr = 0.5 + 0.5 * light_probe_props.z;
- float vertWt = smoothstep(ctr-roughness*0.25, ctr+roughness*0.25, smpUV.y);
- float wtScaled = mix(1.0, vertWt, light_probe_props.z + 1.0);
- retVal *= wtScaled;
- }
-
- return retVal * wt;
-}
-
-vec2 textureSizeLod( vec2 size, int level )
-{
- return size / pow(2.0, float(level));
-}
-
-vec3 getProbeAnisoSample( vec3 smpDir, float roughU, float roughV, mat3 tanFrame )
-{
- float minRough = min(roughU, roughV);
- float maxRough = max(roughU, roughV);
-
- float lodMin = log2( (minRough*3.0 + maxRough)*0.25 ) + (light_probe_offset.w - 2.0);
-
- float ratio = clamp( maxRough / minRough, 1.01, 27.0);
- vec2 texSize = textureSizeLod( light_probe_size, int(floor( lodMin )) );
- texSize = mix( texSize, texSize * 0.5, fract(lodMin) );
-
- // Boundary of 1.0..9.0 is just to keep the number of samples to within a
- // reasonable number of samples in the filter. Similarly, with the clamping
- // of the ratio to a max of 27.0 is just to prevent the step size in the filter
- // to be no bigger than 3 texels (beyond which, there are some artifacts at high
- // roughness, aka low texture res).
- float stepFig = clamp(floor( ratio ), 1.0, 9.0);
-
- // numSteps is half the number of samples we need to take, which makes it
- // the number of steps to take on each side.
- int numSteps = int( floor(stepFig * 0.5) );
-
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
- vec4 result = vec4(0.0);
-
- vec3 smpDirOfs = (maxRough == roughU) ? 0.01 * tanFrame[0] : 0.01 * tanFrame[1];
- vec2 stepPos = getProbeSampleUV(normalize(smpDir + smpDirOfs), light_probe_rotation, light_probe_offset.xy);
- vec2 stepNeg = getProbeSampleUV(normalize(smpDir - smpDirOfs), light_probe_rotation, light_probe_offset.xy);
- stepPos -= smpUV; stepNeg -= smpUV;
- stepPos *= texSize; stepNeg *= texSize;
-
- // This ensures that we step along a size that makes sense even if one of the two
- // sammpling directions wraps around the edges of the IBL texture.
- smpDirOfs /= min( length(stepPos), length(stepNeg) );
- smpDirOfs *= ratio / stepFig;
-
- float sigma = mix(0.0, 2.0, ratio / 27.0);
- sigma *= sigma;
-
- float wt = (1.0 / (ratio - 1.0)) + 1.0;
- result.xyz += wt * getProbeWeightedSample( smpDir, lodMin, minRough, tanFrame[2] );
- result.w += wt;
- for (int i = 0; i < numSteps; ++i)
- {
- wt = sigma / (sigma + float(i * i));
- vec2 uv0 = getProbeSampleUV(normalize(smpDir + smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
- vec2 uv1 = getProbeSampleUV(normalize(smpDir - smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
- result.xyz += wt * textureLod( light_probe, uv0 , lodMin ).xyz;
- result.w += wt;
- result.xyz += wt * textureLod( light_probe, uv1 , lodMin ).xyz;
- result.w += wt;
- }
-
- result /= result.w;
- return result.xyz;
-}
-
-vec4 sampleDiffuse( mat3 tanFrame )
-{
- if ( light_probe_props.w < 0.005 )
- return vec4( 0.0 );
-
-// if ( light_probe_offset.w > 0.5 )
-// {
- // The LOD offset comes from the assumption that a full diffuse convolution
- // has a support of pi/2, which translates into x pixels, and the base 2 log
- // gives us this LOD... Technically, "x" pixels depends on what the original
- // texture resolution was, which is why we use light_probe_offset.w, which holds
- // the number of mip levels the texture has.
-
- return vec4( light_probe_props.w * getProbeWeightedSample( tanFrame[2], light_probe_offset.w - 2.65149613, 1.0, tanFrame[2] ), 1.0 );
-// }
-
- /*
- // PKC -- the code below is for full-blown IBL, which we'll skip for now
-
- // Hand-calculated Hammersley points for t = 2, n = 33
- // I exclude the 0,0 first point, hence why n=33 and not 32
- // Nice thing about 2d Hammersley points is that any subset is
- // also stratified, so even if I have 1000 points and truncate
- // anywhere, I'm fine. Each of these represent the y of an xy
- // while x for the kth point is always (k+1)/n.
- float kernel[32];
- kernel[0] = 0.5; kernel[1] = 0.25;
- kernel[2] = 0.75; kernel[3] = 0.125;
- kernel[4] = 0.625; kernel[5] = 0.375;
- kernel[6] = 0.875; kernel[7] = 0.0625;
- kernel[8] = 0.5625; kernel[9] = 0.3125;
- kernel[10] = 0.8125; kernel[11] = 0.1875;
- kernel[12] = 0.6875; kernel[13] = 0.4375;
- kernel[14] = 0.9375; kernel[15] = 0.03125;
- kernel[16] = 0.53125; kernel[17] = 0.28125;
- kernel[18] = 0.78125; kernel[19] = 0.15625;
- kernel[20] = 0.65625; kernel[21] = 0.40625;
- kernel[22] = 0.90625; kernel[23] = 0.09375;
- kernel[24] = 0.59375; kernel[25] = 0.34375;
- kernel[26] = 0.84375; kernel[27] = 0.28175;
- kernel[28] = 0.71875; kernel[29] = 0.46875;
- kernel[30] = 0.96875; kernel[31] = 0.015625;
-
- float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
-
- vec3 ret = vec3(0, 0, 0);
-
- int ct = 24;
- float step = 25.0;
-
- // Importance sampling a cosine-weighted distribution. Since this
- // matches the BSDF exactly, we are just going to assume that the PDF
- // and the BSDF cancel out in sampling, so we just need to accumulate
- // texture colors. The noise function puts randomized "twist" into
- // the sampled directions.
- for( int i = 0; i < ct; ++i )
- {
- vec3 localDir;
- float phi = 6.28318530718 * (kernel[i] + phiShift);
- float cosTheta = sqrt( float(i+1) / step);
- localDir.z = sqrt(1.0 - cosTheta*cosTheta);
- localDir.x = cos(phi) * cosTheta;
- localDir.y = sin(phi) * cosTheta;
- vec3 smpDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
-
-
- float lodShift = light_probe_offset.w - 2 + log2( 3.1415926535 / (localDir.z * step) );
- vec3 smpColor = getProbeSample( smpDir, lodShift, tanFrame[2] );
-
- // The assumption here is that the BSDF and the sampling PDF are identical
- // so they cancel out and therefore, we don't need to include it here.
- ret += smpColor;
- }
-
- ret *= aoFactor / 24.0;
- return ret;
- */
-}
-
-vec4 sampleDiffuseCustomMaterial( vec3 normal, vec3 worldPos, float aoFactor )
-{
-
- mat3 tanFrame = tangentFrame( normal, worldPos );
- return sampleDiffuse( tanFrame );
-}
-
-vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughU, float roughV )
-{
- if ( light_probe_props.w < 0.005 )
- return vec4( 0.0 );
-
- // PKC : If we do the full IBL sampling, it's useful to square the roughnesses because
- // it makes the effect of roughness feel more linear in the low end. This isn't necessary
- // for fast IBL.
-// float sigmaU = clamp(roughU*roughU, 0.0001, 1.0);
-// float sigmaV = clamp(roughV*roughV, 0.0001, 1.0);
- float sigmaU = smoothstep( 0.0, 1.0, clamp(roughU, 0.0001, 1.0) );
- float sigmaV = smoothstep( 0.0, 1.0, clamp(roughV, 0.0001, 1.0) );
- vec3 ret = vec3(0, 0, 0);
-
-// if ( light_probe_offset.w > 0.5 )
-// {
- vec3 smpDir = reflect( -viewDir, tanFrame[2] );
- float sigma = sqrt(sigmaU * sigmaV);
-
- // Compute the Geometric occlusion/self-shadowing term
- float NdotL = clamp( dot( smpDir, tanFrame[2] ), 0.0, 0.999995);
- float k = sigma * 0.31830988618; // roughness / pi
- float Gl = clamp( (NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
-
- vec3 outColor;
-
- outColor = getProbeAnisoSample( smpDir, sigmaU, sigmaV, tanFrame );
-
- return vec4( light_probe_props.w * Gl * outColor, 1.0 );
-// }
-
- // PKC -- the code below is for full-blown IBL, which we'll skip for now
-
-/*
- float step = clamp( ceil(32.0 * sqrt(max(sigmaU, sigmaV))), 4.0, 32.0 );
- int actualCt = int(step);
- float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
-
- // Hand-calculated Hammersley points for t = 2, n = 33
- // I exclude the 0,0 first point, hence why n=33 and not 32
- // Nice thing about 2d Hammersley points is that any subset is
- // also stratified, so even if I have 1000 points and truncate
- // anywhere, I'm fine. Each of these represent the y of an xy
- // while x for the kth point is always (k+1)/n.
- float kernel[32];
- kernel[0] = 0.5; kernel[1] = 0.25;
- kernel[2] = 0.75; kernel[3] = 0.125;
- kernel[4] = 0.625; kernel[5] = 0.375;
- kernel[6] = 0.875; kernel[7] = 0.0625;
- kernel[8] = 0.5625; kernel[9] = 0.3125;
- kernel[10] = 0.8125; kernel[11] = 0.1875;
- kernel[12] = 0.6875; kernel[13] = 0.4375;
- kernel[14] = 0.9375; kernel[15] = 0.03125;
- kernel[16] = 0.53125; kernel[17] = 0.28125;
- kernel[18] = 0.78125; kernel[19] = 0.15625;
- kernel[20] = 0.65625; kernel[21] = 0.40625;
- kernel[22] = 0.90625; kernel[23] = 0.09375;
- kernel[24] = 0.59375; kernel[25] = 0.34375;
- kernel[26] = 0.84375; kernel[27] = 0.28175;
- kernel[28] = 0.71875; kernel[29] = 0.46875;
- kernel[30] = 0.96875; kernel[31] = 0.015625;
-
- float thetaI = acos( dot(viewDir, tanFrame[2]) );
-
- // NOTE : The model I'm using here is actually based on the KGGX model used in
- // physGlossyBSDF. This is my own variation on the original GGX which uses something
- // closer to a pure Cauchy distribution in tangent space, but also supports anisotropy.
- for (int i = 0; i < actualCt; ++i)
- {
- vec3 localDir;
-
- float phi = 6.28318530718 * (kernel[i] + phiShift);
- float u = float(i + 1) / (step + 1.0);
- float rU = cos(phi) * sigmaU;
- float rV = sin(phi) * sigmaV;
- float sigma = sqrt(rU * rU + rV * rV);
-
- float boundA = atan( ((thetaI - 1.57079632679) * 0.5) / sigma );
- float boundB = atan( ((thetaI + 1.57079632679) * 0.5) / sigma );
- float t = (1.0 - u) * boundA + u * boundB;
- float thetaH = tan( t ) * sigma;
-
- float cosThetaH = cos( thetaH );
- float sinThetaH = sin( thetaH );
- localDir.z = cosThetaH;
- localDir.y = sin(phi) * sinThetaH;
- localDir.x = cos(phi) * sinThetaH;
-
- vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
- halfDir = normalize(halfDir);
- vec3 smpDir = reflect( -viewDir, halfDir );
-
- vec2 scaledXY = localDir.xy / vec2(sigmaU, sigmaV);
- float PDF = (sigmaU*sigmaV) / (sigmaU*sigmaV + dot(scaledXY, scaledXY));
- vec3 Haf = smpDir + viewDir; // We need the unnormalized half vecter as well as the normalized one
- float HdotL = dot(halfDir, smpDir);
- // normalize the PDF to compute the filter support
- // This gives us the ideal miplevel at which to sample the texture map.
- PDF *= dot(Haf, Haf) / (4.0 * dot(Haf, smpDir) * HdotL * sigmaU*sigmaV * (boundB-boundA)*(boundB-boundA));
-
- // Again assuming that the pdf and BSDF are equivalent -- that's not generally valid,
- // but it saves a lot of ALU cycles.
- float lodShift = log2( 512.0 * sigma / PDF );
-
- float k = sigma * 0.31830988618; // roughness / pi
- float Gl = clamp( (HdotL / (HdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
-
- vec3 smpColor = Gl * getProbeSample( smpDir, lodShift, tanFrame[2] );
- ret += smpColor;
- }
- ret /= float(actualCt);
- return vec4(ret, 1.0);
-*/
-}
-
-vec4 sampleGlossy( mat3 tanFrame, vec3 viewDir, float roughness )
-{
- return sampleGlossyAniso( tanFrame, viewDir, roughness, roughness );
-}
-
-vec4 sampleGlossyCustomMaterial( vec3 normal, vec3 worldPos, vec3 viewDir, float roughness )
-{
- mat3 tanFrame = tangentFrame( normal, worldPos );
- return sampleGlossy( tanFrame, viewDir, roughness );
-}
-
-#endif
diff --git a/res/effectlib/gles2/sampleProbePre.glsllib b/res/effectlib/gles2/sampleProbePre.glsllib
new file mode 100644
index 0000000..6127566
--- /dev/null
+++ b/res/effectlib/gles2/sampleProbePre.glsllib
@@ -0,0 +1,7 @@
+
+uniform vec4 light_probe_size;
+
+ivec2 lightProbeSize(sampler2D lightProbe, int lodLevel)
+{
+ return ivec2(light_probe_size / pow(2.0, float(lodLevel)));
+}
diff --git a/res/effectlib/luminance.glsllib b/res/effectlib/luminance.glsllib
index 067dc18..e4ce386 100644
--- a/res/effectlib/luminance.glsllib
+++ b/res/effectlib/luminance.glsllib
@@ -32,31 +32,11 @@
#define LUMINANCE_GLSLLIB
// Luma coefficients according to ITU-R Recommendation BT.709 (http://en.wikipedia.org/wiki/Rec._709)
-const vec3 yCoeff_709 = vec3( 0.2126, 0.7152, 0.0722 );
+const vec3 yCoeff_709 = vec3(0.2126, 0.7152, 0.0722);
-float luminance( in vec3 v )
+float luminance(in vec3 v)
{
- return dot( v, yCoeff_709 );
+ return dot(v, yCoeff_709);
}
-vec3 RGBToYPbPr( in vec3 v )
-{
- vec3 ypp;
- ypp.x = luminance( v );
- ypp.y = 0.5 * (v.b - ypp.x) / (1.0 - yCoeff_709.b);
- ypp.z = 0.5 * (v.r - ypp.x) / (1.0 - yCoeff_709.r);
-
- return ypp;
-}
-
-vec3 YPbPrToRGB( in vec3 v )
-{
- vec3 outRGB;
- outRGB.x = dot(vec3(1.0, 0.0, 1.575), v);
- outRGB.y = dot(vec3(1.0, -0.187, -0.468), v);
- outRGB.z = dot(vec3(1.0, 1.856, 0.0), v);
-
- return outRGB;
-}
-
-#endif \ No newline at end of file
+#endif
diff --git a/res/effectlib/sampleProbe.glsllib b/res/effectlib/sampleProbe.glsllib
index 6556e51..4846ee3 100644
--- a/res/effectlib/sampleProbe.glsllib
+++ b/res/effectlib/sampleProbe.glsllib
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt 3D Studio.
@@ -31,6 +31,10 @@
#ifndef SAMPLE_PROBE_GLSLLIB
#define SAMPLE_PROBE_GLSLLIB 1
+#include "sampleProbePre.glsllib"
+
+#define USE_RGBE
+
uniform sampler2D light_probe;
uniform vec4 light_probe_props;
uniform vec4 light_probe_rotation;
@@ -47,52 +51,54 @@ uniform vec4 light_probe_opts;
float noise1d(vec2 n)
{
- return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
+ return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
-mat3 orthoNormalize( in mat3 tanFrame )
+mat3 orthoNormalize(in mat3 tanFrame)
{
mat3 outMat;
- outMat[0] = normalize( cross( tanFrame[1], tanFrame[2] ) );
- outMat[1] = normalize( cross( tanFrame[2], outMat[0] ) );
+ outMat[0] = normalize(cross(tanFrame[1], tanFrame[2]));
+ outMat[1] = normalize(cross(tanFrame[2], outMat[0]));
outMat[2] = tanFrame[2];
return outMat;
}
-mat3 tangentFrame( vec3 N, vec3 p )
+mat3 tangentFrame(vec3 N, vec3 p)
{
// get edge vectors of the pixel triangle
- vec3 dp1 = dFdx( p );
- vec3 dp2 = dFdy( p );
- // Using dPdu and dPdv would be nicer, but the nature of our materials
- // are not ones with intrinsic UVs, so we can't really go there.
-// vec2 duv1 = dFdx( uv );
-// vec2 duv2 = dFdy( uv );
-
+ vec3 dp1 = dFdx(p);
+ vec3 dp2 = dFdy(p);
// solve the linear system
- vec3 dp2perp = cross( dp2, N );
- vec3 dp1perp = cross( N, dp1 );
-// vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
-// vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
-
+ vec3 dp2perp = cross(dp2, N);
+ vec3 dp1perp = cross(N, dp1);
vec3 T = normalize(dp1perp);
vec3 B = normalize(dp2perp);
- return mat3( T , B , N );
+ return mat3(T, B, N);
}
-vec2 transformSample( vec2 origUV, vec4 probeRot, vec2 probeOfs )
+vec2 transformSample(vec2 origUV, vec4 probeRot, vec2 probeOfs)
{
vec2 retUV;
- retUV.x = dot( vec3(origUV, 1.0), vec3(probeRot.xy, probeOfs.x) );
- retUV.y = dot( vec3(origUV, 1.0), vec3(probeRot.zw, probeOfs.y) );
+ retUV.x = dot(vec3(origUV, 1.0), vec3(probeRot.xy, probeOfs.x));
+ retUV.y = dot(vec3(origUV, 1.0), vec3(probeRot.zw, probeOfs.y));
return retUV;
}
+vec3 textureProbe(sampler2D lightProbe, vec2 coord, float lod)
+{
+#ifdef USE_RGBE
+ vec4 ret = textureLod(lightProbe, coord, lod);
+ return ret.rgb * pow(2.0, ret.a * 255.0 - 128.0);
+#else
+ return textureLod(lightProbe, coord, lod).rgb;
+#endif
+}
+
// This is broken out into its own routine so that if we get some other
// format image than a lat-long, then we can account for that by changing
// the code here alone.
-vec2 getProbeSampleUV( vec3 smpDir, vec4 probeRot, vec2 probeOfs )
+vec2 getProbeSampleUV(vec3 smpDir, vec4 probeRot, vec2 probeOfs)
{
vec2 smpUV;
@@ -114,86 +120,83 @@ vec2 getProbeSampleUV( vec3 smpDir, vec4 probeRot, vec2 probeOfs )
return smpUV;
}
-vec4 getTopLayerSample( vec3 inDir, float lodShift, vec3 lodOffsets )
+vec4 getTopLayerSample(vec3 inDir, float lodShift, vec3 lodOffsets)
{
#if QT3DS_ENABLE_LIGHT_PROBE_2
- if ( light_probe2_props.w < 0.5 )
+ if (light_probe2_props.w < 0.5)
return vec4(0.0, 0.0, 0.0, 0.0);
- vec2 smpUV = getProbeSampleUV( inDir, vec4(1.0, 0.0, 0.0, 1.0), light_probe_props.xy );
+ vec2 smpUV = getProbeSampleUV(inDir, vec4(1.0, 0.0, 0.0, 1.0), light_probe_props.xy);
smpUV.x -= 0.5;
smpUV.x *= light_probe2_props.x;
smpUV.x += light_probe2_props.y;
- vec4 retVal = 0.4 * textureLod( light_probe2, smpUV , lodShift );
- retVal += 0.2 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.x );
- retVal += 0.3 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.y );
- retVal += 0.1 * textureLod( light_probe2, smpUV , lodShift+lodOffsets.z );
+ vec4 retVal = 0.4 * textureLod(light_probe2, smpUV , lodShift);
+ retVal += 0.2 * textureLod(light_probe2, smpUV, lodShift+lodOffsets.x);
+ retVal += 0.3 * textureLod(light_probe2, smpUV, lodShift+lodOffsets.y);
+ retVal += 0.1 * textureLod(light_probe2, smpUV, lodShift+lodOffsets.z);
return retVal;
#else
return vec4(0.0, 0.0, 0.0, 0.0);
#endif
}
-vec3 getProbeSample( vec3 smpDir, float lodShift, vec3 normal )
+vec3 getProbeSample(vec3 smpDir, float lodShift, vec3 normal)
{
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
- return textureLod( light_probe, smpUV , lodShift ).xyz;
+ vec2 smpUV = getProbeSampleUV(smpDir, light_probe_rotation, light_probe_offset.xy);
+ return textureProbe(light_probe, smpUV , lodShift);
}
-vec3 getProbeWeightedSample( vec3 smpDir, float lodShift, float roughness, vec3 normal )
+vec3 getProbeWeightedSample(vec3 smpDir, float lodShift, float roughness, vec3 normal)
{
// This gives us a weighted sum that approximates the total filter support
// of the full-blown convolution.
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
+ vec2 smpUV = getProbeSampleUV(smpDir, light_probe_rotation, light_probe_offset.xy);
float wt = 1.0;
#if QT3DS_ENABLE_IBL_FOV
wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.x));
wt = min(wt, smoothstep(roughness * -0.25, roughness * 0.25, smpUV.y));
- wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.x));
- wt = min(wt, 1.0 - smoothstep(1.0 - roughness*0.25, 1.0 + roughness*0.25, smpUV.y));
+ wt = min(wt, 1.0 - smoothstep(1.0 - roughness * 0.25, 1.0 + roughness * 0.25, smpUV.x));
+ wt = min(wt, 1.0 - smoothstep(1.0 - roughness * 0.25, 1.0 + roughness * 0.25, smpUV.y));
#endif
vec3 lodOffsets;
lodOffsets.x = mix(-2.0, -0.70710678, roughness);
- lodOffsets.y = min( 2.0 * smoothstep(0.0, 0.1, roughness), 2.0 - 1.29289 * smoothstep(0.1, 1.0, roughness) );
- lodOffsets.z = min( 6.0 * smoothstep(0.0, 0.1, roughness), 6.0 - 4.585786 * smoothstep(0.1, 1.0, roughness) );
+ lodOffsets.y = min(2.0 * smoothstep(0.0, 0.1, roughness), 2.0 - 1.29289 * smoothstep(0.1, 1.0, roughness));
+ lodOffsets.z = min(6.0 * smoothstep(0.0, 0.1, roughness), 6.0 - 4.585786 * smoothstep(0.1, 1.0, roughness));
- ivec2 iSize = textureSize(light_probe, 0);
- vec3 ddx = dFdx( smpDir ) * float(iSize.x);
- vec3 ddy = dFdy( smpDir ) * float(iSize.y);
-// vec2 ddxUV = dFdx( smpUV ) * float(iSize.x);
-// vec2 ddyUV = dFdy( smpUV ) * float(iSize.y);
+ ivec2 iSize = lightProbeSize(light_probe, 0);
+ vec3 ddx = dFdx(smpDir) * float(iSize.x);
+ vec3 ddy = dFdy(smpDir) * float(iSize.y);
vec2 deriv;
- deriv.x = max( dot(ddx, ddx), dot(ddy, ddy) );
-// deriv.y = max( dot(ddxUV, ddxUV), dot(ddyUV, ddyUV) );
- deriv = clamp( deriv, vec2(1.0), vec2(iSize.x * iSize.y) );
- vec2 lodBound = 0.5 * log2( deriv ) - vec2(1.0);
+ deriv.x = max(dot(ddx, ddx), dot(ddy, ddy));
+
+ deriv = clamp(deriv, vec2(1.0), vec2(iSize.x * iSize.y));
+ vec2 lodBound = 0.5 * log2(deriv) - vec2(1.0);
-// float minLod = 0.5 * (lodBound.x + lodBound.y);
float minLod = lodBound.x;
- float maxLod = log2( max(float(iSize.x), float(iSize.y)) );
- minLod = clamp( minLod / maxLod, 0.0, 1.0 );
+ float maxLod = log2(max(float(iSize.x), float(iSize.y)));
+ minLod = clamp(minLod / maxLod, 0.0, 1.0);
minLod *= minLod * maxLod;
- lodShift = max( lodShift, minLod );
+ lodShift = max(lodShift, minLod);
- vec3 retVal = 0.4 * textureLod( light_probe, smpUV , lodShift ).xyz;
- retVal += 0.2 * textureLod( light_probe, smpUV , max(minLod, lodShift+lodOffsets.x) ).xyz;
- retVal += 0.3 * textureLod( light_probe, smpUV , lodShift+lodOffsets.y ).xyz;
- retVal += 0.1 * textureLod( light_probe, smpUV , lodShift+lodOffsets.z ).xyz;
+ vec3 retVal = 0.4 * textureProbe(light_probe, smpUV , lodShift);
+ retVal += 0.2 * textureProbe(light_probe, smpUV , max(minLod, lodShift+lodOffsets.x));
+ retVal += 0.3 * textureProbe(light_probe, smpUV , lodShift+lodOffsets.y);
+ retVal += 0.1 * textureProbe(light_probe, smpUV , lodShift+lodOffsets.z);
#if QT3DS_ENABLE_LIGHT_PROBE_2
- vec4 topSmp = getTopLayerSample( smpDir, lodShift, lodOffsets );
- vec3 tempVal = mix( retVal, topSmp.xyz, topSmp.w );
- retVal = mix( retVal, tempVal, light_probe2_props.z );
+ vec4 topSmp = getTopLayerSample(smpDir, lodShift, lodOffsets);
+ vec3 tempVal = mix(retVal, topSmp.xyz, topSmp.w);
+ retVal = mix(retVal, tempVal, light_probe2_props.z);
#endif
if (light_probe_props.z > -1.0) {
float ctr = 0.5 + 0.5 * light_probe_props.z;
- float vertWt = smoothstep(ctr-roughness*0.25, ctr+roughness*0.25, smpUV.y);
+ float vertWt = smoothstep(ctr-roughness * 0.25, ctr+roughness * 0.25, smpUV.y);
float wtScaled = mix(1.0, vertWt, light_probe_props.z + 1.0);
retVal *= wtScaled;
}
@@ -201,273 +204,40 @@ vec3 getProbeWeightedSample( vec3 smpDir, float lodShift, float roughness, vec3
return retVal * wt;
}
-vec3 getProbeAnisoSample( vec3 smpDir, float roughU, float roughV, mat3 tanFrame )
+vec4 sampleDiffuse(mat3 tanFrame)
{
- float minRough = min(roughU, roughV);
- float maxRough = max(roughU, roughV);
-
- float lodMin = log2( (minRough*3.0 + maxRough)*0.25 ) + (light_probe_offset.w - 2.0);
-
- float ratio = clamp( maxRough / minRough, 1.01, 27.0);
- vec2 texSize = vec2( textureSize( light_probe, int(floor( lodMin )) ) );
- texSize = mix( texSize, texSize * 0.5, fract(lodMin) );
-
- // Boundary of 1.0..9.0 is just to keep the number of samples to within a
- // reasonable number of samples in the filter. Similarly, with the clamping
- // of the ratio to a max of 27.0 is just to prevent the step size in the filter
- // to be no bigger than 3 texels (beyond which, there are some artifacts at high
- // roughness, aka low texture res).
- float stepFig = clamp(floor( ratio ), 1.0, 9.0);
-
- // numSteps is half the number of samples we need to take, which makes it
- // the number of steps to take on each side.
- int numSteps = int( floor(stepFig * 0.5) );
-
- vec2 smpUV = getProbeSampleUV( smpDir, light_probe_rotation, light_probe_offset.xy );
- vec4 result = vec4(0.0);
-
- vec3 smpDirOfs = (maxRough == roughU) ? 0.01 * tanFrame[0] : 0.01 * tanFrame[1];
- vec2 stepPos = getProbeSampleUV(normalize(smpDir + smpDirOfs), light_probe_rotation, light_probe_offset.xy);
- vec2 stepNeg = getProbeSampleUV(normalize(smpDir - smpDirOfs), light_probe_rotation, light_probe_offset.xy);
- stepPos -= smpUV; stepNeg -= smpUV;
- stepPos *= texSize; stepNeg *= texSize;
-
- // This ensures that we step along a size that makes sense even if one of the two
- // sammpling directions wraps around the edges of the IBL texture.
- smpDirOfs /= min( length(stepPos), length(stepNeg) );
- smpDirOfs *= ratio / stepFig;
-
- float sigma = mix(0.0, 2.0, ratio / 27.0);
- sigma *= sigma;
-
- float wt = (1.0 / (ratio - 1.0)) + 1.0;
- result.xyz += wt * getProbeWeightedSample( smpDir, lodMin, minRough, tanFrame[2] );
- result.w += wt;
- for (int i = 0; i < numSteps; ++i)
- {
- wt = sigma / (sigma + float(i * i));
- vec2 uv0 = getProbeSampleUV(normalize(smpDir + smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
- vec2 uv1 = getProbeSampleUV(normalize(smpDir - smpDirOfs * float(i)), light_probe_rotation, light_probe_offset.xy);
- result.xyz += wt * textureLod( light_probe, uv0 , lodMin ).xyz;
- result.w += wt;
- result.xyz += wt * textureLod( light_probe, uv1 , lodMin ).xyz;
- result.w += wt;
- }
+ if (light_probe_props.w < 0.005)
+ return vec4(0.0);
- result /= result.w;
- return result.xyz;
+ return vec4(light_probe_props.w * getProbeWeightedSample(tanFrame[2], light_probe_offset.w - 2.65149613, 1.0, tanFrame[2]), 1.0 );
}
-vec4 sampleDiffuse( mat3 tanFrame )
+vec4 sampleDiffuseCustomMaterial(vec3 normal, vec3 worldPos, float aoFactor)
{
- if ( light_probe_props.w < 0.005 )
- return vec4( 0.0 );
-
-// if ( light_probe_offset.w > 0.5 )
-// {
- // The LOD offset comes from the assumption that a full diffuse convolution
- // has a support of pi/2, which translates into x pixels, and the base 2 log
- // gives us this LOD... Technically, "x" pixels depends on what the original
- // texture resolution was, which is why we use light_probe_offset.w, which holds
- // the number of mip levels the texture has.
-
- return vec4( light_probe_props.w * getProbeWeightedSample( tanFrame[2], light_probe_offset.w - 2.65149613, 1.0, tanFrame[2] ), 1.0 );
-// }
-
- /*
- // PKC -- the code below is for full-blown IBL, which we'll skip for now
-
- // Hand-calculated Hammersley points for t = 2, n = 33
- // I exclude the 0,0 first point, hence why n=33 and not 32
- // Nice thing about 2d Hammersley points is that any subset is
- // also stratified, so even if I have 1000 points and truncate
- // anywhere, I'm fine. Each of these represent the y of an xy
- // while x for the kth point is always (k+1)/n.
- float kernel[32];
- kernel[0] = 0.5; kernel[1] = 0.25;
- kernel[2] = 0.75; kernel[3] = 0.125;
- kernel[4] = 0.625; kernel[5] = 0.375;
- kernel[6] = 0.875; kernel[7] = 0.0625;
- kernel[8] = 0.5625; kernel[9] = 0.3125;
- kernel[10] = 0.8125; kernel[11] = 0.1875;
- kernel[12] = 0.6875; kernel[13] = 0.4375;
- kernel[14] = 0.9375; kernel[15] = 0.03125;
- kernel[16] = 0.53125; kernel[17] = 0.28125;
- kernel[18] = 0.78125; kernel[19] = 0.15625;
- kernel[20] = 0.65625; kernel[21] = 0.40625;
- kernel[22] = 0.90625; kernel[23] = 0.09375;
- kernel[24] = 0.59375; kernel[25] = 0.34375;
- kernel[26] = 0.84375; kernel[27] = 0.28175;
- kernel[28] = 0.71875; kernel[29] = 0.46875;
- kernel[30] = 0.96875; kernel[31] = 0.015625;
-
- float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
-
- vec3 ret = vec3(0, 0, 0);
-
- int ct = 24;
- float step = 25.0;
-
- // Importance sampling a cosine-weighted distribution. Since this
- // matches the BSDF exactly, we are just going to assume that the PDF
- // and the BSDF cancel out in sampling, so we just need to accumulate
- // texture colors. The noise function puts randomized "twist" into
- // the sampled directions.
- for( int i = 0; i < ct; ++i )
- {
- vec3 localDir;
- float phi = 6.28318530718 * (kernel[i] + phiShift);
- float cosTheta = sqrt( float(i+1) / step);
- localDir.z = sqrt(1.0 - cosTheta*cosTheta);
- localDir.x = cos(phi) * cosTheta;
- localDir.y = sin(phi) * cosTheta;
- vec3 smpDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
-
-
- float lodShift = light_probe_offset.w - 2 + log2( 3.1415926535 / (localDir.z * step) );
- vec3 smpColor = getProbeSample( smpDir, lodShift, tanFrame[2] );
-
- // The assumption here is that the BSDF and the sampling PDF are identical
- // so they cancel out and therefore, we don't need to include it here.
- ret += smpColor;
- }
-
- ret *= aoFactor / 24.0;
- return ret;
- */
+ mat3 tanFrame = tangentFrame(normal, worldPos);
+ return sampleDiffuse(tanFrame);
}
-vec4 sampleDiffuseCustomMaterial( vec3 normal, vec3 worldPos, float aoFactor )
+vec4 sampleGlossy(mat3 tanFrame, vec3 viewDir, float roughness)
{
+ if (light_probe_props.w < 0.005)
+ return vec4(0.0);
- mat3 tanFrame = tangentFrame( normal, worldPos );
- return sampleDiffuse( tanFrame );
-}
-
-vec4 sampleGlossyAniso( mat3 tanFrame, vec3 viewDir, float roughU, float roughV )
-{
- if ( light_probe_props.w < 0.005 )
- return vec4( 0.0 );
-
- // PKC : If we do the full IBL sampling, it's useful to square the roughnesses because
- // it makes the effect of roughness feel more linear in the low end. This isn't necessary
- // for fast IBL.
-// float sigmaU = clamp(roughU*roughU, 0.0001, 1.0);
-// float sigmaV = clamp(roughV*roughV, 0.0001, 1.0);
- float sigmaU = smoothstep( 0.0, 1.0, clamp(roughU, 0.0001, 1.0) );
- float sigmaV = smoothstep( 0.0, 1.0, clamp(roughV, 0.0001, 1.0) );
+ float sigma = smoothstep(0.0, 1.0, clamp(roughness, 0.0001, 1.0));
vec3 ret = vec3(0, 0, 0);
-// if ( light_probe_offset.w > 0.5 )
-// {
- vec3 smpDir = reflect( -viewDir, tanFrame[2] );
- float sigma = sqrt(sigmaU * sigmaV);
-
- // Compute the Geometric occlusion/self-shadowing term
- float NdotL = clamp( dot( smpDir, tanFrame[2] ), 0.0, 0.999995);
- float k = sigma * 0.31830988618; // roughness / pi
- float Gl = clamp( (NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
-
- vec3 outColor;
-
- outColor = getProbeAnisoSample( smpDir, sigmaU, sigmaV, tanFrame );
-
- return vec4( light_probe_props.w * Gl * outColor, 1.0 );
-// }
-
- // PKC -- the code below is for full-blown IBL, which we'll skip for now
-
-/*
- float step = clamp( ceil(32.0 * sqrt(max(sigmaU, sigmaV))), 4.0, 32.0 );
- int actualCt = int(step);
- float phiShift = noise1d(gl_FragCoord.xy) - 0.5;
-
- // Hand-calculated Hammersley points for t = 2, n = 33
- // I exclude the 0,0 first point, hence why n=33 and not 32
- // Nice thing about 2d Hammersley points is that any subset is
- // also stratified, so even if I have 1000 points and truncate
- // anywhere, I'm fine. Each of these represent the y of an xy
- // while x for the kth point is always (k+1)/n.
- float kernel[32];
- kernel[0] = 0.5; kernel[1] = 0.25;
- kernel[2] = 0.75; kernel[3] = 0.125;
- kernel[4] = 0.625; kernel[5] = 0.375;
- kernel[6] = 0.875; kernel[7] = 0.0625;
- kernel[8] = 0.5625; kernel[9] = 0.3125;
- kernel[10] = 0.8125; kernel[11] = 0.1875;
- kernel[12] = 0.6875; kernel[13] = 0.4375;
- kernel[14] = 0.9375; kernel[15] = 0.03125;
- kernel[16] = 0.53125; kernel[17] = 0.28125;
- kernel[18] = 0.78125; kernel[19] = 0.15625;
- kernel[20] = 0.65625; kernel[21] = 0.40625;
- kernel[22] = 0.90625; kernel[23] = 0.09375;
- kernel[24] = 0.59375; kernel[25] = 0.34375;
- kernel[26] = 0.84375; kernel[27] = 0.28175;
- kernel[28] = 0.71875; kernel[29] = 0.46875;
- kernel[30] = 0.96875; kernel[31] = 0.015625;
-
- float thetaI = acos( dot(viewDir, tanFrame[2]) );
-
- // NOTE : The model I'm using here is actually based on the KGGX model used in
- // physGlossyBSDF. This is my own variation on the original GGX which uses something
- // closer to a pure Cauchy distribution in tangent space, but also supports anisotropy.
- for (int i = 0; i < actualCt; ++i)
- {
- vec3 localDir;
-
- float phi = 6.28318530718 * (kernel[i] + phiShift);
- float u = float(i + 1) / (step + 1.0);
- float rU = cos(phi) * sigmaU;
- float rV = sin(phi) * sigmaV;
- float sigma = sqrt(rU * rU + rV * rV);
-
- float boundA = atan( ((thetaI - 1.57079632679) * 0.5) / sigma );
- float boundB = atan( ((thetaI + 1.57079632679) * 0.5) / sigma );
- float t = (1.0 - u) * boundA + u * boundB;
- float thetaH = tan( t ) * sigma;
-
- float cosThetaH = cos( thetaH );
- float sinThetaH = sin( thetaH );
- localDir.z = cosThetaH;
- localDir.y = sin(phi) * sinThetaH;
- localDir.x = cos(phi) * sinThetaH;
-
- vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
- halfDir = normalize(halfDir);
- vec3 smpDir = reflect( -viewDir, halfDir );
-
- vec2 scaledXY = localDir.xy / vec2(sigmaU, sigmaV);
- float PDF = (sigmaU*sigmaV) / (sigmaU*sigmaV + dot(scaledXY, scaledXY));
- vec3 Haf = smpDir + viewDir; // We need the unnormalized half vecter as well as the normalized one
- float HdotL = dot(halfDir, smpDir);
- // normalize the PDF to compute the filter support
- // This gives us the ideal miplevel at which to sample the texture map.
- PDF *= dot(Haf, Haf) / (4.0 * dot(Haf, smpDir) * HdotL * sigmaU*sigmaV * (boundB-boundA)*(boundB-boundA));
-
- // Again assuming that the pdf and BSDF are equivalent -- that's not generally valid,
- // but it saves a lot of ALU cycles.
- float lodShift = log2( 512.0 * sigma / PDF );
-
- float k = sigma * 0.31830988618; // roughness / pi
- float Gl = clamp( (HdotL / (HdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
-
- vec3 smpColor = Gl * getProbeSample( smpDir, lodShift, tanFrame[2] );
- ret += smpColor;
- }
- ret /= float(actualCt);
- return vec4(ret, 1.0);
-*/
-}
+ vec3 smpDir = reflect(-viewDir, tanFrame[2]);
-vec4 sampleGlossy( mat3 tanFrame, vec3 viewDir, float roughness )
-{
- return sampleGlossyAniso( tanFrame, viewDir, roughness, roughness );
-}
+ // Compute the Geometric occlusion/self-shadowing term
+ float NdotL = clamp(dot(smpDir, tanFrame[2]), 0.0, 0.999995);
+ float k = sigma * 0.31830988618; // roughness / pi
+ float Gl = clamp((NdotL / (NdotL*(1.0-k) + k) + (1.0 - k*k)) * 0.5, 0.0, 1.0 );
-vec4 sampleGlossyCustomMaterial( vec3 normal, vec3 worldPos, vec3 viewDir, float roughness )
-{
- mat3 tanFrame = tangentFrame( normal, worldPos );
- return sampleGlossy( tanFrame, viewDir, roughness );
+ vec3 outColor;
+
+ outColor = getProbeSample(smpDir, sigma, tanFrame[2]);
+
+ return vec4(light_probe_props.w * Gl * outColor, 1.0);
}
#endif
diff --git a/res/effectlib/sampleProbePre.glsllib b/res/effectlib/sampleProbePre.glsllib
new file mode 100644
index 0000000..5fd42c9
--- /dev/null
+++ b/res/effectlib/sampleProbePre.glsllib
@@ -0,0 +1,5 @@
+
+ivec2 lightProbeSize(sampler2D lightProbe, int lodLevel)
+{
+ return ivec2(textureSize(lightProbe, lodLevel));
+}
diff --git a/res/effectlib/specularBSDF.glsllib b/res/effectlib/specularBSDF.glsllib
index 78e541a..028e6fb 100644
--- a/res/effectlib/specularBSDF.glsllib
+++ b/res/effectlib/specularBSDF.glsllib
@@ -32,16 +32,16 @@
#ifndef DEFAULT_MATERIAL_LIGHTING
-vec4 specularBSDFEnvironment( in vec3 N, in vec3 viewDir, in vec3 tint, int mode )
+vec4 specularBSDFEnvironment(in vec3 N, in vec3 viewDir, in vec3 tint, int mode)
{
- vec3 rgb = vec3( 0.0, 0.0, 0.0 );
- if ( uEnvironmentMappingEnabled )
- {
- vec3 R = reflect( -viewDir, N );
- rgb = evalEnvironmentMap( R, 0.0 );
- rgb = specularBSDF( N, R, viewDir, rgb, 1.0, 256.0, tint, scatter_reflect ).rgb;
- }
- return( vec4( rgb, 1.0 ) );
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+ if ( uEnvironmentMappingEnabled )
+ {
+ vec3 R = reflect(-viewDir, N);
+ rgb = evalEnvironmentMap(R, 0.0);
+ rgb = specularBSDF(N, R, viewDir, rgb, 256.0).rgb;
+ }
+ return vec4(rgb, 1.0);
}
#endif
diff --git a/res/effectlib/transformCoordinate.glsllib b/res/effectlib/transformCoordinate.glsllib
index ccdf7d0..cbe20e7 100644
--- a/res/effectlib/transformCoordinate.glsllib
+++ b/res/effectlib/transformCoordinate.glsllib
@@ -40,4 +40,13 @@ texture_coordinate_info transformCoordinate( in mat4 transform, in texture_coord
return( tci );
}
+texture_coordinate_info scaleCoordinate(in vec3 scale, in texture_coordinate_info coordinate)
+{
+ texture_coordinate_info tci;
+ tci.position = scale * coordinate.position;
+ tci.tangent_u = scale * coordinate.tangent_u;
+ tci.tangent_v = scale * coordinate.tangent_v;
+ return tci;
+}
+
#endif
diff --git a/src/3rdparty/EASTL b/src/3rdparty/EASTL
-Subproject 31697c758f2ed19bd7c6bbe61f1b91f9e12035b
+Subproject 0d1d5505c1e6c2af3f77680979d9b237e9fbf35
diff --git a/src/api/studio3d/doc/qt3dstudio-opengl-runtime-project.qdocconf b/src/api/studio3d/doc/qt3dstudio-opengl-runtime-project.qdocconf
index ece96a5..3e8de94 100644
--- a/src/api/studio3d/doc/qt3dstudio-opengl-runtime-project.qdocconf
+++ b/src/api/studio3d/doc/qt3dstudio-opengl-runtime-project.qdocconf
@@ -15,7 +15,7 @@ headerdirs += ../.. \
imagedirs += ./src/images
-depends = qtcore qtgui qtwidgets qtqml qtquick qtquickcontrols qt3dstudio qt3dstudioruntime2 qtdoc qmake
+depends = qtcore qtgui qtwidgets qtqml qtquick qtquickcontrols qtdoc qmake
qhp.projects = QtStudio3D
@@ -55,9 +55,7 @@ buildversion = "Qt 3D Studio OpenGL Runtime $QT_VER Manual"
macro.RUNTIME = Qt 3D Studio OpenGL Runtime
-#TODO: adjust these once we have runtime-specific examples
-# examplesinstallpath = studio3d
-# exampledirs += ../examples/studio3d
+examplesinstallpath = studio3d
+exampledirs += ../../../../examples/studio3d
Cpp.ignoretokens += Q3DSV_EXPORT Q_STUDIO3D_EXPORT
-depends += qt3d
diff --git a/src/api/studio3d/doc/src/building-opengl-runtime.qdoc b/src/api/studio3d/doc/src/building-opengl-runtime.qdoc
index b9d95b5..30822bb 100644
--- a/src/api/studio3d/doc/src/building-opengl-runtime.qdoc
+++ b/src/api/studio3d/doc/src/building-opengl-runtime.qdoc
@@ -30,6 +30,61 @@
\title Building the \RUNTIME
\page building-opengl-runtime.html
+\section1 Build Settings
+
+To configure runtime features you can modify \c ogl-runtime\commonplatform.pri file.
+This file contains defines which turn on / off specific features.
+
+\section2 Performance Logging
+Enable \c QT3DS_ENABLE_PERF_LOGGING to build runtime with performance logging on. At runtime, to see the logs
+you should also enable \c qt3ds.perf_info category e.g. with \c "QT_LOGGING_RULES=qt3ds.perf_info=true".
+More information about Qt logging categories from \l {https://doc.qt.io/qt-5/qloggingcategory.html}
+
+During the application startup console output should then contain following:
+
+\badcode
+qt3ds.perf_info: 1. (1) Application: Begin Load - 1.145900ms = 1.146200ms
+qt3ds.perf_info: 2. (1) Context: CreateRenderContext - 192.358500ms = 193.522300ms
+qt3ds.perf_info: 3. (1) Binding: Initial Batch Image Load - 0.003200ms = 193.551800ms
+qt3ds.perf_info: 4. (1) Binding: Initialize Scenes - 0.000100ms = 193.563500ms
+qt3ds.perf_info: 5. (1) SceneManager: OnGraphicsInitialized - 0.023800ms = 193.567600ms
+qt3ds.perf_info: 6. (1) Application: EndLoad - 0.000500ms = 193.574900ms
+qt3ds.perf_info: 7. (1) Application: GetMetaData - 59.171400ms = 252.875800ms
+qt3ds.perf_info: 8. (3) BatchLoader: Image Decompression - 15.395400ms = 294.876900ms
+...
+qt3ds.perf_info: 36. (1) Application: NotifyDataOutputs - 0.080800ms = 477.483800ms
+qt3ds.perf_info: *** First frame rendered ***
+qt3ds.perf_info: Runtime startup time: 477ms
+qt3ds.perf_info: Application startup time: 1601ms
+qt3ds.perf_info: Render Statistics: 33.62fps, frame count 34
+qt3ds.perf_info: Render Statistics: 59.92fps, frame count 60
+qt3ds.perf_info: Render Statistics: 59.92fps, frame count 60
+...
+\endcode
+
+Log format is: \c {(n) [task name] - [time] = [cumulative time]} where:
+\list
+ \li \c (n) = The amount of time \c [task name] was run during startup.
+ \li \c [task name] = Method/task being logged.
+ \li \c [time] = How many ms running \c [task name] for \c (n) times totally takes.
+ \li \c [cumulative time] = How many total ms has passed when the last run of \c [task name] ends.
+\endlist
+
+\note When analyzing the results, please note that tasks overlap with each other, some tasks include other tasks etc.
+\c {Runtime startup time} contains the time spent inside runtime methods where \c {Application startup time} contains the whole startup time.
+
+\note \c QT3DS_ENABLE_PERF_LOGGING should not be enabled in release builds as logging increases performance overhead.
+
+\section2 Shadows and Lights
+To optimize the supported shadows and lights amount, you can define QT3DS_MAX_NUM_LIGHTS and QT3DS_MAX_NUM_SHADOWS.
+
+\section2 Legacy ASTC
+To enable legacy ASTC which means that ASTC files are not loaded until needed for texture creation, define LEGACY_ASTC_LOADING.
+
+\section2 Premultiplied ASTC
+To force all ASTC compressed images to be treated as premultiplied, you can enable this. Alternatively if you want
+to do this at runtime, set QT3DS_ALL_ASTC_PREMULTIPLIED as an environment variable.
+
\section1 Build Instructions
\list
diff --git a/src/api/studio3d/doc/src/gettingstarted.qdoc b/src/api/studio3d/doc/src/gettingstarted.qdoc
index 9289b54..a80c919 100644
--- a/src/api/studio3d/doc/src/gettingstarted.qdoc
+++ b/src/api/studio3d/doc/src/gettingstarted.qdoc
@@ -68,10 +68,7 @@
\li Qt Quick: here applications import QtStudio3D.OpenGL \QtVer which
provides the \l [QML] Studio3D QML type, a Qt Quick item that can be
- added to Qt Quick scenes. Under the hood this is similar to adding a
- \l [QML] Scene3D (when working directly with the lower level Qt 3D
- framework) or a custom item based on \l QQuickFramebufferObject into
- the scene.
+ added to Qt Quick scenes.
\li QWindow or offscreen render targets (OpenGL texture): Q3DSSurfaceViewer
can be used both to render to an on-screen QWindow, as well as off-screen
diff --git a/src/api/studio3d/q3dscommandqueue.cpp b/src/api/studio3d/q3dscommandqueue.cpp
index b2d0937..18aeb78 100644
--- a/src/api/studio3d/q3dscommandqueue.cpp
+++ b/src/api/studio3d/q3dscommandqueue.cpp
@@ -217,6 +217,12 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
m_stereoModeChanged = m_stereoModeChanged || fromQueue.m_stereoModeChanged;
m_stereoEyeSeparationChanged
= m_stereoEyeSeparationChanged || fromQueue.m_stereoEyeSeparationChanged;
+ m_stereoEyeRotationChanged
+ = m_stereoEyeRotationChanged || fromQueue.m_stereoEyeRotationChanged;
+ m_stereoProgressiveEnabledChanged
+ = m_stereoProgressiveEnabledChanged || fromQueue.m_stereoProgressiveEnabledChanged;
+ m_skipFramesIntervalChanged
+ = m_skipFramesIntervalChanged || fromQueue.m_skipFramesIntervalChanged;
m_shadeModeChanged = m_shadeModeChanged || fromQueue.m_shadeModeChanged;
m_showRenderStatsChanged = m_showRenderStatsChanged || fromQueue.m_showRenderStatsChanged;
m_matteColorChanged = m_matteColorChanged || fromQueue.m_matteColorChanged;
@@ -236,6 +242,12 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
m_stereoMode = fromQueue.m_stereoMode;
if (fromQueue.m_stereoEyeSeparationChanged)
m_stereoEyeSeparation = fromQueue.m_stereoEyeSeparation;
+ if (fromQueue.m_stereoEyeRotationChanged)
+ m_stereoEyeRotation = fromQueue.m_stereoEyeRotation;
+ if (fromQueue.m_stereoProgressiveEnabledChanged)
+ m_stereoProgressiveEnabled = fromQueue.m_stereoProgressiveEnabled;
+ if (fromQueue.m_skipFramesIntervalChanged)
+ m_skipFramesInterval = fromQueue.m_skipFramesInterval;
if (fromQueue.m_shadeModeChanged)
m_shadeMode = fromQueue.m_shadeMode;
if (fromQueue.m_showRenderStatsChanged)
@@ -338,6 +350,9 @@ void CommandQueue::clear(bool deleteCommandData)
m_scaleModeChanged = false;
m_stereoModeChanged = false;
m_stereoEyeSeparationChanged = false;
+ m_stereoEyeRotationChanged = false;
+ m_stereoProgressiveEnabledChanged = false;
+ m_skipFramesIntervalChanged = false;
m_shadeModeChanged = false;
m_showRenderStatsChanged = false;
m_matteColorChanged = false;
diff --git a/src/api/studio3d/q3dscommandqueue_p.h b/src/api/studio3d/q3dscommandqueue_p.h
index 0b7b833..15d9397 100644
--- a/src/api/studio3d/q3dscommandqueue_p.h
+++ b/src/api/studio3d/q3dscommandqueue_p.h
@@ -143,6 +143,9 @@ public:
bool m_scaleModeChanged = false;
bool m_stereoModeChanged = false;
bool m_stereoEyeSeparationChanged = false;
+ bool m_stereoEyeRotationChanged = false;
+ bool m_stereoProgressiveEnabledChanged = false;
+ bool m_skipFramesIntervalChanged = false;
bool m_shadeModeChanged = false;
bool m_showRenderStatsChanged = false;
bool m_matteColorChanged = false;
@@ -157,6 +160,9 @@ public:
Q3DSViewerSettings::ScaleMode m_scaleMode = Q3DSViewerSettings::ScaleModeCenter;
Q3DSViewerSettings::StereoMode m_stereoMode = Q3DSViewerSettings::StereoModeMono;
double m_stereoEyeSeparation = 0.4;
+ double m_stereoEyeRotation = 0.0;
+ bool m_stereoProgressiveEnabled = false;
+ int m_skipFramesInterval = 0;
Q3DSViewerSettings::ShadeMode m_shadeMode = Q3DSViewerSettings::ShadeModeShaded;
bool m_showRenderStats = false;
QColor m_matteColor = QColor(Qt::black);
diff --git a/src/api/studio3d/q3dsdatainput.cpp b/src/api/studio3d/q3dsdatainput.cpp
index 232fd0e..c98e6b4 100644
--- a/src/api/studio3d/q3dsdatainput.cpp
+++ b/src/api/studio3d/q3dsdatainput.cpp
@@ -112,10 +112,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \dontdocument QMetaTypeId
-*/
-
-/*!
\internal
*/
Q3DSDataInput::Q3DSDataInput(QObject *parent)
@@ -410,28 +406,6 @@ void Q3DSDataInputPrivate::setCommandQueue(CommandQueue *queue)
}
/*!
- \qmlproperty string DataInput::name
-
- Specifies the name of the controlled data input element in the
- presentation. This property must be set as part of DataInput declaration,
- although it is changeable afterwards, if desired.
-*/
-
-/*!
- \qmlproperty variant DataInput::value
-
- Specifies the value of the controlled data input element in the presentation.
-
- The value of this property only accounts for changes done via the same
- DataInput instance. If the value of the underlying attribute in the
- presentation is changed elsewhere, for example via animations or
- Presentation::setAttribute(), those changes are not reflected in the value
- of this property. Due to this uncertainty, this property treats all value
- sets as changes even if the newly set value is the same value as the
- previous value.
-*/
-
-/*!
\qmlproperty real DataInput::min
Contains the minimum value of the controlled data input element range.
@@ -461,4 +435,18 @@ void Q3DSDataInputPrivate::setCommandQueue(CommandQueue *queue)
\note This value is read-only.
*/
+/*!
+ \property Q3DSDataInput::metadataKeys
+
+ Contains the metadata keys specified for this datainput.
+
+ \note This value is read-only.
+*/
+
+/*!
+ \qmlmethod list<string> DataInput::metadataKeys
+
+ Contains the metadata keys specified for this datainput.
+*/
+
QT_END_NAMESPACE
diff --git a/src/api/studio3d/q3dsdatainput.h b/src/api/studio3d/q3dsdatainput.h
index 8d6cff7..0465b43 100644
--- a/src/api/studio3d/q3dsdatainput.h
+++ b/src/api/studio3d/q3dsdatainput.h
@@ -77,10 +77,10 @@ Q_SIGNALS:
protected:
explicit Q3DSDataInput(Q3DSDataInputPrivate *d, Q3DSPresentation *presentation,
const QString &name, QObject *parent = nullptr);
- Q3DSDataInputPrivate *d_ptr;
private:
Q_DISABLE_COPY(Q3DSDataInput)
+ Q3DSDataInputPrivate *d_ptr;
friend class Q3DSPresentationPrivate;
friend class Q3DSPresentation;
friend class Q3DSRenderer;
diff --git a/src/api/studio3d/q3dsgeometry.cpp b/src/api/studio3d/q3dsgeometry.cpp
index f4b650a..d8bc463 100644
--- a/src/api/studio3d/q3dsgeometry.cpp
+++ b/src/api/studio3d/q3dsgeometry.cpp
@@ -287,7 +287,9 @@ void Q3DSGeometry::addAttribute(Q3DSGeometry::Attribute::Semantic semantic,
}
/*!
- This is an overloaded function.
+ Sets an attribute \a att to this geometry.
+
+ \sa addAttribute
*/
void Q3DSGeometry::addAttribute(const Q3DSGeometry::Attribute &att)
{
diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp
index 50a9d6c..c711bbc 100644
--- a/src/api/studio3d/q3dspresentation.cpp
+++ b/src/api/studio3d/q3dspresentation.cpp
@@ -91,7 +91,6 @@ QT_BEGIN_NAMESPACE
/*!
\qmltype Presentation
- \instantiates Q3DSPresentationItem
\inqmlmodule QtStudio3D.OpenGL
\ingroup OpenGLRuntime
\inherits Q3DSPresentation
@@ -617,7 +616,7 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath)
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.
+ compressed shader source code is exported.
Exporting shader cache is an asynchronous operation.
The shaderCacheExported signal is emitted when the export is complete.
@@ -629,13 +628,13 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath)
from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
with shaderCacheFile property allows shader generation.
- \sa shaderCacheFile, shaderCacheExported
+ \sa shaderCacheFile, shaderCacheExported, qCompress
*/
/*!
\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.
+ compressed shader source code is exported.
The shaderCacheExported signal is emitted when the export is complete.
@@ -646,15 +645,11 @@ void Q3DSPresentation::unloadSlide(const QString &elementPath)
from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
with shaderCacheFile property allows shader generation.
- \sa shaderCacheFile, shaderCacheExported
+ \sa shaderCacheFile, shaderCacheExported, qCompress
*/
void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binaryShaders)
{
- d_ptr->exportShaderCache(binaryShaders, false);
- if (d_ptr->m_commandQueue)
- d_ptr->m_shaderCacheWritePending = shaderCacheFile;
- else
- d_ptr->writeShaderCache(shaderCacheFile);
+ exportShaderCache(shaderCacheFile, binaryShaders, -1);
}
/*!
@@ -668,7 +663,7 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar
a command line parameter \c --convert-shader-cache to do this conversion.
If \a binaryShaders property is \c{true}, precompiled shaders are exported.
- Otherwise, the shader source code is exported.
+ Otherwise, compressed shader source code is exported.
Exporting shader cache is an asynchronous operation.
The shaderCacheExported signal is emitted when the export is complete.
@@ -680,7 +675,7 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar
from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
with shaderCacheFile property allows shader generation.
- \sa shaderCacheFile, shaderCacheExported
+ \sa shaderCacheFile, shaderCacheExported, qCompress
*/
/*!
\since Qt 3D Studio 2.5
@@ -691,7 +686,7 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar
a command line parameter \c --convert-shader-cache to do this conversion.
If \a binaryShaders property is \c{true}, precompiled shaders are exported.
- Otherwise, the shader source code is exported.
+ Otherwise, compressed shader source code is exported.
The shaderCacheExported signal is emitted when the export is complete.
@@ -702,11 +697,182 @@ void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binar
from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
with shaderCacheFile property allows shader generation.
- \sa shaderCacheFile, shaderCacheExported
+ \sa shaderCacheFile, shaderCacheExported, qCompress
*/
void Q3DSPresentation::exportShaderCache(bool binaryShaders)
{
- d_ptr->exportShaderCache(binaryShaders, true);
+ exportShaderCache(binaryShaders, -1);
+}
+
+/*!
+ \since Qt 3D Studio 2.6
+ Exports the shaders currently in use to a byte array specified by \a cacheData parameter.
+ If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise,
+ compressed shader source code is exported.
+
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache.
+
+ \sa setShaderCacheData, shaderCacheExported, qCompress
+ */
+void Q3DSPresentation::exportShaderCache(QByteArray &cacheData, bool binaryShaders)
+{
+ exportShaderCache(cacheData, binaryShaders, -1);
+}
+
+/*!
+ \qmlmethod Presentation::exportShaderCache(url shaderCacheFile, bool binaryShaders, int compressionLevel)
+ \since QtStudio3D.OpenGL 2.7
+
+ 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,
+ compressed shader source code is exported.
+ The exported shaders are compressed using compression level specified by \a{compressionLevel}.
+ \c{-1} means default qCompress compression level. \c{0} means no compression.
+
+ Exporting shader cache is an asynchronous operation.
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
+ with shaderCacheFile property allows shader generation.
+
+ \sa shaderCacheFile, shaderCacheExported, qCompress
+ */
+/*!
+ \since Qt 3D Studio 2.7
+ 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,
+ compressed shader source code is exported.
+ The exported shaders are compressed using compression level specified by \a{compressionLevel}.
+ \c{-1} means default qCompress compression level. \c{0} means no compression.
+
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
+ with shaderCacheFile property allows shader generation.
+
+ \sa shaderCacheFile, shaderCacheExported, qCompress
+ */
+void Q3DSPresentation::exportShaderCache(const QUrl &shaderCacheFile, bool binaryShaders,
+ int compressionLevel)
+{
+ d_ptr->exportShaderCache(binaryShaders, false, compressionLevel);
+ if (d_ptr->m_commandQueue)
+ d_ptr->m_shaderCacheWritePending = shaderCacheFile;
+ else
+ d_ptr->writeShaderCache(shaderCacheFile);
+}
+
+/*!
+ \qmlmethod Presentation::exportShaderCache(bool binaryShaders, int compressionLevel)
+ \since QtStudio3D.OpenGL 2.7
+
+ 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
+ representation to be usable as a shader cache file. The Qt 3D Studio Viewer provides
+ a command line parameter \c --convert-shader-cache to do this conversion.
+
+ If \a binaryShaders property is \c{true}, precompiled shaders are exported.
+ Otherwise, compressed shader source code is exported.
+ The exported shaders are compressed using compression level specified by \a{compressionLevel}.
+ \c{-1} means default qCompress compression level. \c{0} means no compression.
+
+ Exporting shader cache is an asynchronous operation.
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
+ with shaderCacheFile property allows shader generation.
+
+ \sa shaderCacheFile, shaderCacheExported, qCompress
+ */
+/*!
+ \since Qt 3D Studio 2.7
+ 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
+ representation to be usable as a shader cache file. The Qt 3D Studio Viewer provides
+ a command line parameter \c --convert-shader-cache to do this conversion.
+
+ If \a binaryShaders property is \c{true}, precompiled shaders are exported.
+ Otherwise, compressed shader source code is exported.
+ The exported shaders are compressed using compression level specified by \a{compressionLevel}.
+ \c{-1} means default qCompress compression level. \c{0} means no compression.
+
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache. Specifying no shader cache file or an empty or invalid shader cache file
+ with shaderCacheFile property allows shader generation.
+
+ \sa shaderCacheFile, shaderCacheExported, qCompress
+ */
+void Q3DSPresentation::exportShaderCache(bool binaryShaders, int compressionLevel)
+{
+ d_ptr->exportShaderCache(binaryShaders, true, compressionLevel);
+}
+
+/*!
+ \since Qt 3D Studio 2.7
+ Exports the shaders currently in use to a byte array specified by \a cacheData parameter.
+ If \a binaryShaders property is \c{true}, precompiled shaders are exported. Otherwise,
+ compressed shader source code is exported.
+ The exported shaders are compressed using compression level specified by \a{compressionLevel}.
+ \c{-1} means default qCompress compression level. \c{0} means no compression.
+
+ The shaderCacheExported signal is emitted when the export is complete.
+
+ Exporting shader cache should be done at the point of application execution where all the
+ shaders that should be initialized at application startup have been initialized.
+
+ \note Exporting shader cache is only supported if no shaders have been originally loaded
+ from a shader cache.
+
+ \sa setShaderCacheData, shaderCacheExported, qCompress
+ */
+void Q3DSPresentation::exportShaderCache(QByteArray &cacheData, bool binaryShaders,
+ int compressionLevel)
+{
+ d_ptr->exportShaderCache(binaryShaders, false, compressionLevel);
+ d_ptr->getShaderCacheData(cacheData);
+}
+
+/*!
+ \since Qt 3D Studio 2.6
+ Specifies the \a shaderCache data to be used for initial shader initialization.
+ This method must be called before the presentation is shown.
+ Using cached shaders improves presentation initialization speed.
+
+ If this method is not called and shaderCacheFile property is not set, all shaders are generated
+ normally.
+
+ If this method is called, new shader cache generation is not supported.
+
+ \sa exportShaderCache(), shaderCacheFile
+ */
+void Q3DSPresentation::setShaderCacheData(const QByteArray &shaderCache)
+{
+ d_ptr->m_shaderCacheImport = shaderCache;
}
/*!
@@ -724,22 +890,24 @@ void Q3DSPresentation::exportShaderCache(bool binaryShaders)
The default value is an empty url.
- \sa exportShaderCache(), shaderCacheExport
+ \sa exportShaderCache()
*/
/*!
+ \property Q3DSPresentation::shaderCacheFile
\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.
- If this property is not set, all shaders are generated normally.
+ If this property is not set and setShaderCacheData is not called, all shaders are generated
+ normally.
If this property points to a valid shader cache file, new shader cache generation is not
supported.
The default value is an empty url.
- \sa exportShaderCache(), shaderCacheExport
+ \sa exportShaderCache(), setShaderCacheData
*/
QUrl Q3DSPresentation::shaderCacheFile() const
{
@@ -761,7 +929,7 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName)
Emitted when a shader cache export is completed. The parameter \a success indicates whether
or not the export was successful.
- \sa shaderCacheExport(), shaderCacheFile
+ \sa exportShaderCache(), shaderCacheFile
*/
/*!
@@ -771,7 +939,23 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName)
Emitted when a shader cache export is completed. The parameter \a success indicates whether
or not the export was successful.
- \sa shaderCacheExport(), shaderCacheFile
+ \sa exportShaderCache(), shaderCacheFile
+ */
+
+/*!
+ \qmlsignal Presentation::shaderCacheLoadErrors(string errors)
+ \since QtStudio3D.OpenGL 2.7
+
+ Emitted when a shader cache loading fails. The parameter \a errors contains the error
+ message(s).
+ */
+
+/*!
+ \fn Q3DSPresentation::shaderCacheLoadErrors(const QString &errors)
+ \since Qt 3D Studio 2.7
+
+ Emitted when a shader cache loading fails. The parameter \a errors contains the error
+ message(s).
*/
/*!
@@ -781,7 +965,7 @@ void Q3DSPresentation::setShaderCacheFile(const QUrl &fileName)
Requests a time context (a Scene or a Component object) to change
to a specific slide by \a index. If the context is already on that
- slide, playback will start over.
+ slide, playback will start over. Slide indexing starts from one.
If \a elementPath points to a time context, that element is
controlled. For all other element types the time context owning
@@ -958,6 +1142,30 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a
"image://colors/blue" where "image://" tells the runtime to look for an
image provider, "colors" is the image provider id and rest are the image
id the provider uses to create the image.
+
+ Usage is similar to the examples in https://doc.qt.io/qt-5/qquickimageprovider.html
+
+ \badcode
+ // Example implementation of a request function
+ // This returns a 50 x 50 px size green texture as a QPixmap
+ QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+ {
+ // Size needs to be more than 0,0 or nothing will be drawn
+ if (size)
+ *size = QSize(50, 50);
+
+ QPixmap pixmap(50, 50);
+ pixmap.fill(QColor("green"));
+ return pixmap;
+ }
+
+ // Image providers are added to the presentation after viewer creation
+ viewer.create(&window, &context);
+ viewer.presentation()->addImageProvider("green", new ImageProvider());
+
+ // Use as texture
+ viewer.presentation()->setAttribute("Scene.Layer.Rectangle.Material.diffusemap", "sourcepath", "image://green");
+ \endcode
*/
void Q3DSPresentation::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
{
@@ -984,6 +1192,25 @@ uint Q3DSPresentation::textureId(const QString &elementPath)
}
/*!
+ \since Qt 3D Studio 2.7
+ Returns the OpenGL texture id associated with a layer or an image specified
+ by \a elementPath. Texture \a size and \a format are returned in corresponding parameters.
+
+ 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, QSize &size, GLenum &format)
+{
+ if (d_ptr->m_viewerApp)
+ return d_ptr->m_viewerApp->textureId(elementPath, size, format);
+
+ size = {};
+ format = GL_INVALID_ENUM;
+ return 0;
+}
+
+/*!
Activate or deactivate the presentation identified by \a id depending
on the value of \a active.
*/
@@ -1067,6 +1294,13 @@ void Q3DSPresentation::setDataInputValue(const QString &name, const QVariant &va
di->d_ptr->m_forced = force;
d_ptr->setDataInputDirty(name, true, d_ptr->m_dataInputCallIndex++);
+
+ // Do not pollute datainput value cache if we are not ready to accept attribute changes.
+ // Datainput will locally hold set value and is marked as dirty, but we do not yet allow
+ // updating the cached value that holds the value we have actually committed to the engine.
+ if (!d_ptr->m_viewerApp && !d_ptr->m_commandQueue)
+ return;
+
// We batch datainput changes within a frame, so just tell the presentation that one
// or more datainputs have changed value.
d_ptr->m_dataInputsChanged = true;
@@ -1120,8 +1354,8 @@ void Q3DSPresentation::createElement(const QString &parentElementPath, const QSt
specified with \a slideName. Element properties are specified in \a properties.
For more details, see createElement().
- \sa createElement()
- \sa elementsCreated()
+ \sa Q3DSPresentation::createElement()
+ \sa Q3DSPresentation::elementsCreated()
*/
void Q3DSPresentation::createElements(const QString &parentElementPath, const QString &slideName,
const QVector<QHash<QString, QVariant>> &properties)
@@ -1182,8 +1416,8 @@ void Q3DSPresentation::deleteElements(const QStringList &elementPaths)
\note Elements can only be dynamically created via C++ API.
- \sa createElement()
- \sa createElements()
+ \sa Q3DSPresentation::createElement()
+ \sa Q3DSPresentation::createElements()
*/
/*!
@@ -1318,9 +1552,6 @@ void Q3DSPresentation::deleteMaterials(const QStringList &materialNames)
This property is read-only.
\note Materials can only be dynamically created via C++ API.
-
- \sa createMaterial()
- \sa createMaterials()
*/
/*!
@@ -1433,9 +1664,6 @@ void Q3DSPresentation::deleteMeshes(const QStringList &meshNames)
This property is read-only.
\note Meshes can only be dynamically created via C++ API.
-
- \sa createMesh()
- \sa createMeshes()
*/
/*!
@@ -1555,7 +1783,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
Emitted when a slide in a presentation or component is entered. \a elementPath
specifies the slide path. \a index and \a name contain the index and
- the name of the entered slide.
+ the name of the entered slide. Slide indexing starts from one.
This signal is emitted for each component, meaning that it can be emitted multiple
times on one slide change.
@@ -1566,7 +1794,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
Emitted when a slide in a presentation or component is entered. \a elementPath
specifies the slide path. \a index and \a name contain the index and
- the name of the entered slide.
+ the name of the entered slide. Slide indexing starts from one.
This signal is emitted for each component, meaning that it can be emitted multiple
times on one slide change.
@@ -1577,7 +1805,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
Emitted when a slide in a presentation or component is exited. \a elementPath
specifies the slide path. \a index and \a name contain the index and
- the name of the exited slide.
+ the name of the exited slide. Slide indexing starts from one.
This signal is emitted for each component, meaning that it can be emitted multiple
times on one slide change.
@@ -1588,7 +1816,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
Emitted when a slide in a presentation or component is exited. \a elementPath
specifies the slide path. \a index and \a name contain the index and
- the name of the exited slide.
+ the name of the exited slide. Slide indexing starts from one.
This signal is emitted for each component, meaning that it can be emitted multiple
times on one slide change.
@@ -1649,8 +1877,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
If creation failed, \a error string indicates the reason.
- \sa createElement()
- \sa createElements()
+ \note Elements can only be dynamically created via C++ API.
*/
/*!
@@ -1674,8 +1901,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
If creation failed, \a error string indicates the reason.
- \sa createMaterial()
- \sa createMaterials()
+ \note Materials can only be dynamically created via C++ API.
*/
/*!
@@ -1700,8 +1926,7 @@ void Q3DSPresentation::keyReleaseEvent(QKeyEvent *e)
If creation failed, \a error string indicates the reason.
- \sa createMesh()
- \sa createMeshes()
+ \note Meshes can only be dynamically created via C++ API.
*/
/*!
@@ -1912,7 +2137,7 @@ void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, vo
if (response->size() > 0)
m_shaderCacheExport = response->at(0).toByteArray();
if (!m_shaderCacheExport.isEmpty())
- m_shaderCacheExport = qCompress(m_shaderCacheExport);
+ m_shaderCacheExport = qCompress(m_shaderCacheExport, m_shaderCacheCompression);
if (!m_shaderCacheWritePending.isEmpty()) {
writeShaderCache(m_shaderCacheWritePending);
m_shaderCacheWritePending.clear();
@@ -1933,8 +2158,10 @@ void Q3DSPresentationPrivate::requestResponseHandler(CommandType commandType, vo
// Writes current shader cache to the specified file in UTF-8 format
void Q3DSPresentationPrivate::writeShaderCache(const QUrl &shaderCacheFile)
{
- if (m_shaderCacheExport.isEmpty())
+ if (m_shaderCacheExport.isEmpty()) {
+ Q_EMIT q_ptr->shaderCacheExported(false);
return; // Warning is already printed by export function
+ }
const QString filePath = shaderCacheFile.toLocalFile();
QSaveFile file(filePath);
QFileInfo(filePath).dir().mkpath(QStringLiteral("."));
@@ -1949,30 +2176,56 @@ void Q3DSPresentationPrivate::writeShaderCache(const QUrl &shaderCacheFile)
Q_EMIT q_ptr->shaderCacheExported(success);
}
+void Q3DSPresentationPrivate::getShaderCacheData(QByteArray &shaderCacheData)
+{
+ bool success = false;
+
+ if (!m_shaderCacheExport.isEmpty()) {
+ shaderCacheData = m_shaderCacheExport;
+ success = true;
+ }
+ Q_EMIT q_ptr->shaderCacheExported(success);
+}
+
QByteArray Q3DSPresentationPrivate::loadShaderCache() const
{
+ QString error;
if (!m_shaderCacheFile.isEmpty()) {
QFile file(Q3DSUtils::urlToLocalFileOrQrc(m_shaderCacheFile));
- if (file.open(QIODevice::ReadOnly))
- return qUncompress(file.readAll());
-
- qWarning() << __FUNCTION__ << "Warning: Failed to read shader cache:"
- << m_shaderCacheFile << file.errorString();
+ if (file.open(QIODevice::ReadOnly)) {
+ const QByteArray data = qUncompress(file.readAll());
+ if (!data.isEmpty())
+ return data;
+ }
+ error = QStringLiteral("Failed to read or uncompress shader cache: %1 '%2'")
+ .arg(m_shaderCacheFile.toString()).arg(file.errorString());
+ } else if (!m_shaderCacheImport.isEmpty()) {
+ const QByteArray data = qUncompress(m_shaderCacheImport);
+ if (data.isEmpty())
+ error = QStringLiteral("Failed uncompress shader cache.");
+ else
+ return data;
}
+
+ if (!error.isEmpty())
+ Q_EMIT q_ptr->shaderCacheLoadErrors(error);
+
return {};
}
-void Q3DSPresentationPrivate::exportShaderCache(bool binaryShaders, bool dumpCache)
+void Q3DSPresentationPrivate::exportShaderCache(bool binaryShaders, bool dumpCache,
+ int compression)
{
if (m_viewerApp) {
m_shaderCacheExport = m_viewerApp->exportShaderCache(binaryShaders);
if (!m_shaderCacheExport.isEmpty())
- m_shaderCacheExport = qCompress(m_shaderCacheExport);
+ m_shaderCacheExport = qCompress(m_shaderCacheExport, compression);
if (dumpCache)
dumpShaderCache();
} else if (m_commandQueue) {
m_commandQueue->queueCommand(CommandType_RequestExportShaderCache, binaryShaders);
m_shaderCacheDumpPending = dumpCache;
+ m_shaderCacheCompression = compression;
}
}
diff --git a/src/api/studio3d/q3dspresentation.h b/src/api/studio3d/q3dspresentation.h
index 5210a29..6d25a74 100644
--- a/src/api/studio3d/q3dspresentation.h
+++ b/src/api/studio3d/q3dspresentation.h
@@ -38,6 +38,7 @@
#include <QtCore/qstringlist.h>
#include <QtStudio3D/q3dsdatainput.h>
#include <QtStudio3D/q3dsdataoutput.h>
+#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
@@ -95,6 +96,12 @@ public:
Q_REVISION(1) Q_INVOKABLE void exportShaderCache(const QUrl &shaderCacheFile,
bool binaryShaders);
Q_REVISION(1) Q_INVOKABLE void exportShaderCache(bool binaryShaders);
+ void exportShaderCache(QByteArray &cacheData, bool binaryShaders);
+ Q_REVISION(2) Q_INVOKABLE void exportShaderCache(const QUrl &shaderCacheFile,
+ bool binaryShaders, int compressionLevel);
+ Q_REVISION(2) Q_INVOKABLE void exportShaderCache(bool binaryShaders, int compressionLevel);
+ void exportShaderCache(QByteArray &cacheData, bool binaryShaders, int compressionLevel);
+ void setShaderCacheData(const QByteArray &shaderCache);
QUrl shaderCacheFile() const;
// Input event handlers
@@ -128,6 +135,7 @@ public:
void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider);
uint textureId(const QString &elementPath);
+ uint textureId(const QString &elementPath, QSize &size, GLenum &format);
public Q_SLOTS:
void setSource(const QUrl &source);
@@ -158,6 +166,7 @@ Q_SIGNALS:
void meshesCreated(const QStringList &meshNames, const QString &error);
void shaderCacheFileChanged(const QUrl &fileName);
void shaderCacheExported(bool success);
+ void shaderCacheLoadErrors(const QString &errors);
private:
Q_DISABLE_COPY(Q3DSPresentation)
diff --git a/src/api/studio3d/q3dspresentation_p.h b/src/api/studio3d/q3dspresentation_p.h
index 0925dff..10f013f 100644
--- a/src/api/studio3d/q3dspresentation_p.h
+++ b/src/api/studio3d/q3dspresentation_p.h
@@ -102,8 +102,9 @@ public:
void requestResponseHandler(CommandType commandType, void *requestData);
void writeShaderCache(const QUrl &shaderCacheFile);
+ void getShaderCacheData(QByteArray &shaderCacheData);
QByteArray loadShaderCache() const;
- void exportShaderCache(bool binaryShaders, bool dumpCache);
+ void exportShaderCache(bool binaryShaders, bool dumpCache, int compression);
void dumpShaderCache();
public Q_SLOTS:
@@ -132,8 +133,10 @@ private:
bool m_dataInputsChanged;
QUrl m_shaderCacheFile;
QByteArray m_shaderCacheExport;
+ QByteArray m_shaderCacheImport;
QUrl m_shaderCacheWritePending;
bool m_shaderCacheDumpPending = false;
+ int m_shaderCacheCompression = -1;
int m_dataInputCallIndex = 0;
friend class Q3DSStudio3D;
diff --git a/src/api/studio3d/q3dssceneelement.cpp b/src/api/studio3d/q3dssceneelement.cpp
index 8de03eb..f241d95 100644
--- a/src/api/studio3d/q3dssceneelement.cpp
+++ b/src/api/studio3d/q3dssceneelement.cpp
@@ -112,6 +112,7 @@ Q3DSSceneElement::~Q3DSSceneElement()
\qmlproperty int SceneElement::currentSlideIndex
Holds the index of the currently active slide of the tracked time context.
+ Slide indexing starts from one.
\note If this property is set to something else than the default slide for
the scene at the initial declaration of SceneElement, a changed signal for
@@ -125,6 +126,7 @@ Q3DSSceneElement::~Q3DSSceneElement()
\property Q3DSSceneElement::currentSlideIndex
Holds the index of the currently active slide of the tracked time context.
+ Slide indexing starts from one.
\note If this property is set to something else than the default slide for
the scene at the initial declaration of SceneElement, a changed signal for
@@ -132,6 +134,8 @@ Q3DSSceneElement::~Q3DSSceneElement()
desired one. This happens in order to ensure we end up with the index of
the slide that is actually shown even if the slide specified in the initial
declaration is invalid.
+
+ \sa Q3DSPresentation::slideEntered()
*/
int Q3DSSceneElement::currentSlideIndex() const
{
@@ -144,13 +148,13 @@ void Q3DSSceneElement::setCurrentSlideIndex(int currentSlideIndex)
Q_D(Q3DSSceneElement);
if (d->m_viewerApp) {
const QByteArray path(d->m_elementPath.toUtf8());
- d->m_viewerApp->GoToSlideByIndex(path, currentSlideIndex + 1);
+ d->m_viewerApp->GoToSlideByIndex(path, currentSlideIndex);
} else if (d->m_commandQueue) {
d->m_commandQueue->queueCommand(d->m_elementPath, CommandType_GoToSlide,
- int(currentSlideIndex + 1));
+ currentSlideIndex);
} else {
// Store desired slide until we have either app or queue. Only name or index can be set.
- d->m_initialSlideIndex = currentSlideIndex + 1;
+ d->m_initialSlideIndex = currentSlideIndex;
d->m_initialSlideName.clear();
}
}
@@ -218,7 +222,7 @@ void Q3DSSceneElement::setCurrentSlideName(const QString &currentSlideName)
} else {
// Store desired slide until we have either app or queue. Only name or index can be set.
d->m_initialSlideName = currentSlideName;
- d->m_initialSlideIndex = 0;
+ d->m_initialSlideIndex = 1;
}
}
@@ -366,12 +370,12 @@ void Q3DSSceneElementPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app)
// If user has set current slide before viewer app has been set for the first time,
// we will switch to the desired slide after we initialize.
- if (m_initialSlideIndex != 0)
- q->setCurrentSlideIndex(m_initialSlideIndex - 1);
+ if (m_initialSlideIndex != 1)
+ q->setCurrentSlideIndex(m_initialSlideIndex);
else if (!m_initialSlideName.isEmpty())
q->setCurrentSlideName(m_initialSlideName);
- m_initialSlideIndex = 0;
+ m_initialSlideIndex = 1;
m_initialSlideName.clear();
}
}
@@ -396,12 +400,12 @@ void Q3DSSceneElementPrivate::setCommandQueue(CommandQueue *queue)
m_slideInfoRequestPending = true;
// If user has set current slide before the queue has been set for the first time,
// we will switch to the desired slide after we initialize.
- if (m_initialSlideIndex != 0)
- q->setCurrentSlideIndex(m_initialSlideIndex - 1);
+ if (m_initialSlideIndex != 1)
+ q->setCurrentSlideIndex(m_initialSlideIndex);
else if (!m_initialSlideName.isEmpty())
q->setCurrentSlideName(m_initialSlideName);
- m_initialSlideIndex = 0;
+ m_initialSlideIndex = 1;
m_initialSlideName.clear();
}
}
diff --git a/src/api/studio3d/q3dssurfaceviewer.cpp b/src/api/studio3d/q3dssurfaceviewer.cpp
index 401cb8f..2d7846c 100644
--- a/src/api/studio3d/q3dssurfaceviewer.cpp
+++ b/src/api/studio3d/q3dssurfaceviewer.cpp
@@ -98,7 +98,7 @@ QT_BEGIN_NAMESPACE
/*!
* \brief Q3DSSurfaceViewer::Q3DSSurfaceViewer Constructor.
- * \param parent Optional parent of the object.
+ * \a parent Optional parent of the object.
*/
Q3DSSurfaceViewer::Q3DSSurfaceViewer(QObject *parent)
: QObject(parent)
@@ -277,6 +277,14 @@ int Q3DSSurfaceViewer::fboId() const
}
/*!
+ \property Q3DSSurfaceViewer::error
+
+ Error string.
+
+ This property is read-only.
+*/
+
+/*!
Returns the error string.
*/
QString Q3DSSurfaceViewer::error() const
@@ -357,6 +365,12 @@ void Q3DSSurfaceViewer::setQmlEngine(QQmlEngine *qmlEngine)
d->qmlEngine = qmlEngine;
}
+/*!
+ \fn Q3DSSurfaceViewer::frameDraw()
+ \since Qt 3D Studio 2.8
+
+ Emitted each time a new image has been drawn for Renderer.
+*/
/*!
\fn Q3DSSurfaceViewer::frameUpdate()
@@ -378,6 +392,12 @@ void Q3DSSurfaceViewer::setQmlEngine(QQmlEngine *qmlEngine)
*/
/*!
+ \fn Q3DSSurfaceViewer::afterRendering()
+
+ Emitted when a frame has been rendered.
+ */
+
+/*!
* \internal
*/
Q3DSSurfaceViewerPrivate::Q3DSSurfaceViewerPrivate(Q3DSSurfaceViewer *q)
@@ -531,7 +551,6 @@ void Q3DSSurfaceViewerPrivate::update()
m_presentation->d_ptr->setDataInputValueBatch();
m_presentation->d_ptr->setDataInputsChanged(false);
}
-
m_viewerApp->Render();
Q_EMIT q_ptr->afterRendering();
@@ -643,7 +662,12 @@ bool Q3DSSurfaceViewerPrivate::initializeRuntime()
this->q_ptr, &Q3DSSurfaceViewer::presentationReady);
connect(m_viewerApp, &Q3DSViewerApp::SigPresentationLoaded,
this->q_ptr, &Q3DSSurfaceViewer::presentationLoaded);
+ connect(m_viewerApp, &Q3DSViewerApp::SigFrameDraw,
+ this->q_ptr, &Q3DSSurfaceViewer::frameDraw);
+ connect(m_viewerApp, &Q3DSViewerApp::SigLoadShaderCacheErrors,
+ m_presentation, &Q3DSPresentation::shaderCacheLoadErrors);
Q_ASSERT(m_viewerApp);
+
}
if (!m_context->makeCurrent(m_surface)) {
qWarning () << "Q3DSSurfaceViewer: Unable to make context current";
diff --git a/src/api/studio3d/q3dssurfaceviewer.h b/src/api/studio3d/q3dssurfaceviewer.h
index b9e4016..3252a2d 100644
--- a/src/api/studio3d/q3dssurfaceviewer.h
+++ b/src/api/studio3d/q3dssurfaceviewer.h
@@ -99,6 +99,7 @@ public Q_SLOTS:
Q_SIGNALS:
void presentationLoaded();
void presentationReady();
+ void frameDraw();
void frameUpdate();
void afterRendering();
void errorChanged();
diff --git a/src/api/studio3d/q3dsviewersettings.cpp b/src/api/studio3d/q3dsviewersettings.cpp
index 7aa11a2..2c3e8db 100644
--- a/src/api/studio3d/q3dsviewersettings.cpp
+++ b/src/api/studio3d/q3dsviewersettings.cpp
@@ -96,6 +96,15 @@ Q3DSViewerSettings::~Q3DSViewerSettings()
*/
/*!
+ \enum Q3DSViewerSettings::ShadeMode
+
+ This enumeration specifies the possible shading modes.
+
+ \value ShadeModeShaded Shades the surfaces normally. This is the default.
+ \value ShadeModeShadedWireframe Renders wireframe on top of shaded surfaces.
+*/
+
+/*!
\qmlproperty QColor ViewerSettings::matteColor
Specifies the matte color.
@@ -155,17 +164,18 @@ void Q3DSViewerSettings::setShowRenderStats(bool show)
}
}
-/*
- //! TODO
- \internal
- \qmlproperty enumeration ViewerSettings::shadeMode
- */
+/*!
+ \fn Q3DSViewerSettings::shadeModeChanged(ShadeMode mode)
-/*
- // TODO
- \internal
- \property Q3DSViewerSettings::shadeMode
+ Emitted when shade \a mode is changed.
+*/
+
+/*!
+ Returns the shading mode used.
+
+ \sa Q3DSViewerSettings::ShadeMode
*/
+
Q3DSViewerSettings::ShadeMode Q3DSViewerSettings::shadeMode() const
{
return d_ptr->m_shadeMode;
@@ -200,21 +210,13 @@ void Q3DSViewerSettings::setShadeMode(Q3DSViewerSettings::ShadeMode mode)
/*!
\property Q3DSViewerSettings::scaleMode
- Specifies the scaling mode. The default value \c is ScaleModeFill where the
- size of the presentation on-screen follows and fills the size of the output
- area (the window, the screen, or the area occupied by the \l Studio3D
- element).
-
- During the design phase it can be valuable to see the presentation with
- some other scaling approach. For example, the Qt 3D Studio Viewer
- application uses ScaleModeCenter by default.
+ Specifies the scaling mode.
\value ScaleModeFit Scales the presentation to fit the output area.
\value ScaleModeFill Scales the presentation to completely fill the output area.
\value ScaleModeCenter Centers the presentation in the output area without scaling it.
+*/
- The default value is \c{ScaleModeFill}.
- */
Q3DSViewerSettings::ScaleMode Q3DSViewerSettings::scaleMode() const
{
return d_ptr->m_scaleMode;
@@ -262,6 +264,20 @@ void Q3DSViewerSettings::setScaleMode(Q3DSViewerSettings::ScaleMode mode)
The default value is \c{StereoModeMono}.
*/
+
+/*!
+ \enum Q3DSViewerSettings::StereoMode
+
+ \since Qt 3D Studio 2.5
+
+ This enumeration specifies the possible stereoscopic viewing modes.
+
+ \value StereoModeMono This is the default value.
+ \value StereoModeTopBottom
+ \value StereoModeLeftRight
+ \value StereoModeAnaglyphRedCyan
+ \value StereoModeAnaglyphGreenMagenta
+*/
Q3DSViewerSettings::StereoMode Q3DSViewerSettings::stereoMode() const
{
return d_ptr->m_stereoMode;
@@ -316,6 +332,125 @@ void Q3DSViewerSettings::setStereoEyeSeparation(double separation)
}
/*!
+ \qmlproperty real ViewerSettings::stereoEyeRotation
+
+ \since QtStudio3D.OpenGL 2.8
+
+ Specifies the eye (camera) rotation of stereo rendering.
+ Value is the amount left and right eye cameras rotate in y-coordinate
+ (horizontally) away from center as radians. Adding rotation moves
+ the eyes convergence distance closer. The default value is 0,
+ meaning convergence point is at infinity.
+
+ This has only effect when stereo mode is set to something else than
+ default \c{StereoModeMono}.
+ */
+/*!
+ \property Q3DSViewerSettings::stereoEyeRotation
+
+ \since Qt 3D Studio 2.8
+
+ Specifies the eye (camera) rotation of stereo rendering.
+ Value is the amount left and right eye cameras rotate in y-coordinate
+ (horizontally) away from center as radians. Adding rotation moves
+ the eyes convergence distance closer. The default value is 0,
+ meaning convergence point is at infinity.
+
+ This has only effect when stereo mode is set to something else than
+ default \c{StereoModeMono}.
+ */
+double Q3DSViewerSettings::stereoEyeRotation() const
+{
+ return d_ptr->m_stereoEyeRotation;
+}
+
+void Q3DSViewerSettings::setStereoEyeRotation(double rotation)
+{
+ if (rotation >= 0
+ && !qFuzzyCompare(d_ptr->m_stereoEyeRotation, rotation)) {
+ d_ptr->setStereoEyeRotation(rotation);
+ Q_EMIT stereoEyeRotationChanged(rotation);
+ }
+}
+
+/*!
+ \qmlproperty bool ViewerSettings::stereoProgressiveEnabled
+
+ \since QtStudio3D.OpenGL 2.7
+
+ Enables progressive rendering in stereoscopic modes. In this mode,
+ only single eye per frame is rendered. Left eye for odd frames and
+ right for even frames. This halves the maximum animation frame rate
+ (meaning e.g. 30fps on 60Hz screen) while decreasing CPU/GPU usage.
+
+ \note This property has only effect when stereo mode is set to
+ \c{StereoModeTopBottom} or \c{StereoModeLeftRight}.
+ */
+/*!
+ \property Q3DSViewerSettings::stereoProgressiveEnabled
+
+ \since Qt 3D Studio 2.7
+
+ Enables progressive rendering in stereoscopic modes. In this mode,
+ only single eye per frame is rendered. Left eye for odd frames and
+ right for even frames. This halves the maximum animation frame rate
+ (meaning e.g. 30fps on 60Hz screen) while decreasing CPU/GPU usage.
+
+ \note This property has only effect when stereo mode is set to
+ \c{StereoModeTopBottom} or \c{StereoModeLeftRight}.
+ */
+bool Q3DSViewerSettings::stereoProgressiveEnabled() const
+{
+ return d_ptr->m_stereoProgressiveEnabled;
+}
+
+void Q3DSViewerSettings::setStereoProgressiveEnabled(bool enabled)
+{
+ if (d_ptr->m_stereoProgressiveEnabled != enabled) {
+ d_ptr->setStereoProgressiveEnabled(enabled);
+ Q_EMIT stereoProgressiveEnabledChanged(enabled);
+ }
+}
+
+/*!
+ \qmlproperty int ViewerSettings::skipFramesInterval
+
+ \since QtStudio3D.OpenGL 2.7
+
+ Sets interval for skipping frame rendering. The default value is 0
+ meaning all frames are rendered. Setting this to 1 renders every
+ other frame (30fps on 60Hz screen), 2 every third frame (20fps on
+ 60Hz screen) etc. This property allows slowing down 3D rendering
+ while keeping QtQuick UI rendering intact, decreasing the CPU/GPU
+ usage.
+ */
+/*!
+ \property Q3DSViewerSettings::skipFramesInterval
+
+ \since Qt 3D Studio 2.7
+
+ Sets interval for skipping frame rendering. The default value is 0
+ meaning all frames are rendered. Setting this to 1 renders every
+ other frame (30fps on 60Hz screen), 2 every third frame (20fps on
+ 60Hz screen) etc. This property allows slowing down 3D rendering
+ while keeping QtQuick UI rendering intact, decreasing the CPU/GPU
+ usage.
+ */
+
+int Q3DSViewerSettings::skipFramesInterval() const
+{
+ return d_ptr->m_skipFramesInterval;
+}
+
+void Q3DSViewerSettings::setSkipFramesInterval(int interval)
+{
+ if (d_ptr->m_skipFramesInterval != interval) {
+ d_ptr->setSkipFramesInterval(interval);
+ Q_EMIT skipFramesIntervalChanged(interval);
+ }
+}
+
+/*!
\qmlproperty bool ViewerSettings::matteEnabled
Specifies if the empty area around the presentation (applicable when
@@ -394,6 +529,9 @@ Q3DSViewerSettingsPrivate::Q3DSViewerSettingsPrivate(Q3DSViewerSettings *q)
, m_scaleMode(Q3DSViewerSettings::ScaleModeCenter)
, m_stereoMode(Q3DSViewerSettings::StereoModeMono)
, m_stereoEyeSeparation(0.4)
+ , m_stereoEyeRotation(0.0)
+ , m_stereoProgressiveEnabled(false)
+ , m_skipFramesInterval(0)
, m_savedSettings(nullptr)
{
}
@@ -413,6 +551,9 @@ void Q3DSViewerSettingsPrivate::setViewerApp(Q3DSViewer::Q3DSViewerApp *app)
setScaleMode(m_scaleMode);
setStereoMode(m_stereoMode);
setStereoEyeSeparation(m_stereoEyeSeparation);
+ setStereoEyeRotation(m_stereoEyeRotation);
+ setStereoProgressiveEnabled(m_stereoProgressiveEnabled);
+ setSkipFramesInterval(m_skipFramesInterval);
}
}
@@ -427,6 +568,9 @@ void Q3DSViewerSettingsPrivate::setCommandQueue(CommandQueue *queue)
setScaleMode(m_scaleMode);
setStereoMode(m_stereoMode);
setStereoEyeSeparation(m_stereoEyeSeparation);
+ setStereoEyeRotation(m_stereoEyeRotation);
+ setStereoProgressiveEnabled(m_stereoProgressiveEnabled);
+ setSkipFramesInterval(m_skipFramesInterval);
}
}
@@ -441,6 +585,7 @@ void Q3DSViewerSettingsPrivate::save(const QString &group, const QString &organi
m_savedSettings->setValue(QStringLiteral("scaleMode"), m_scaleMode);
m_savedSettings->setValue(QStringLiteral("stereoMode"), m_stereoMode);
m_savedSettings->setValue(QStringLiteral("stereoEyeSeparation"), m_stereoEyeSeparation);
+ m_savedSettings->setValue(QStringLiteral("stereoEyeRotation"), m_stereoEyeRotation);
m_savedSettings->setValue(QStringLiteral("matteEnabled"), m_matteEnabled);
}
@@ -459,6 +604,12 @@ void Q3DSViewerSettingsPrivate::load(const QString &group, const QString &organi
m_savedSettings->value(QStringLiteral("stereoMode")).toInt()));
q_ptr->setStereoEyeSeparation(
m_savedSettings->value(QStringLiteral("stereoEyeSeparation")).toDouble());
+ q_ptr->setStereoEyeRotation(
+ m_savedSettings->value(QStringLiteral("stereoEyeRotation")).toDouble());
+ q_ptr->setStereoProgressiveEnabled(
+ m_savedSettings->value(QStringLiteral("stereoProgressiveEnabled")).toBool());
+ q_ptr->setSkipFramesInterval(
+ m_savedSettings->value(QStringLiteral("skipFramesInterval")).toInt());
q_ptr->setMatteEnabled(m_savedSettings->value(QStringLiteral("matteEnabled")).toBool());
}
@@ -556,6 +707,39 @@ void Q3DSViewerSettingsPrivate::setStereoEyeSeparation(double separation)
}
}
+void Q3DSViewerSettingsPrivate::setStereoEyeRotation(double rotation)
+{
+ m_stereoEyeRotation = rotation;
+ if (m_viewerApp) {
+ m_viewerApp->SetStereoEyeRotation(rotation);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_stereoEyeRotation = rotation;
+ m_commandQueue->m_stereoEyeRotationChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setStereoProgressiveEnabled(bool enabled)
+{
+ m_stereoProgressiveEnabled = enabled;
+ if (m_viewerApp) {
+ m_viewerApp->SetStereoProgressiveEnabled(enabled);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_stereoProgressiveEnabled = enabled;
+ m_commandQueue->m_stereoProgressiveEnabledChanged = true;
+ }
+}
+
+void Q3DSViewerSettingsPrivate::setSkipFramesInterval(int interval)
+{
+ m_skipFramesInterval = interval;
+ if (m_viewerApp) {
+ m_viewerApp->SetSkipFramesInterval(interval);
+ } else if (m_commandQueue) {
+ m_commandQueue->m_skipFramesInterval = interval;
+ m_commandQueue->m_skipFramesIntervalChanged = true;
+ }
+}
+
void Q3DSViewerSettingsPrivate::initSettingsStore(const QString &group, const QString &organization,
const QString &application)
{
diff --git a/src/api/studio3d/q3dsviewersettings.h b/src/api/studio3d/q3dsviewersettings.h
index 0a5e699..a0e29d6 100644
--- a/src/api/studio3d/q3dsviewersettings.h
+++ b/src/api/studio3d/q3dsviewersettings.h
@@ -52,6 +52,9 @@ class Q_STUDIO3D_EXPORT Q3DSViewerSettings : public QObject
Q_PROPERTY(ScaleMode scaleMode READ scaleMode WRITE setScaleMode NOTIFY scaleModeChanged)
Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode NOTIFY stereoModeChanged REVISION 1)
Q_PROPERTY(double stereoEyeSeparation READ stereoEyeSeparation WRITE setStereoEyeSeparation NOTIFY stereoEyeSeparationChanged REVISION 1)
+ Q_PROPERTY(bool stereoProgressiveEnabled READ stereoProgressiveEnabled WRITE setStereoProgressiveEnabled NOTIFY stereoProgressiveEnabledChanged REVISION 2)
+ Q_PROPERTY(int skipFramesInterval READ skipFramesInterval WRITE setSkipFramesInterval NOTIFY skipFramesIntervalChanged REVISION 2)
+ Q_PROPERTY(double stereoEyeRotation READ stereoEyeRotation WRITE setStereoEyeRotation NOTIFY stereoEyeRotationChanged REVISION 3)
public:
enum ShadeMode {
@@ -82,6 +85,9 @@ public:
ScaleMode scaleMode() const;
StereoMode stereoMode() const;
double stereoEyeSeparation() const;
+ Q_REVISION(2) bool stereoProgressiveEnabled() const;
+ Q_REVISION(2) int skipFramesInterval() const;
+ Q_REVISION(3) double stereoEyeRotation() const;
Q_INVOKABLE void save(const QString &group, const QString &organization = QString(),
const QString &application = QString());
@@ -95,6 +101,9 @@ public Q_SLOTS:
void setScaleMode(ScaleMode mode);
void setStereoMode(StereoMode mode);
void setStereoEyeSeparation(double separation);
+ Q_REVISION(2) void setStereoProgressiveEnabled(bool enabled);
+ Q_REVISION(2) void setSkipFramesInterval(int interval);
+ Q_REVISION(3) void setStereoEyeRotation(double rotation);
Q_SIGNALS:
void matteEnabledChanged(bool enabled);
@@ -104,6 +113,9 @@ Q_SIGNALS:
void scaleModeChanged(ScaleMode mode);
void stereoModeChanged(StereoMode mode);
void stereoEyeSeparationChanged(double separation);
+ Q_REVISION(2) void stereoProgressiveEnabledChanged(bool enabled);
+ Q_REVISION(2) void skipFramesIntervalChanged(int interval);
+ Q_REVISION(3) void stereoEyeRotationChanged(double rotation);
private:
Q_DISABLE_COPY(Q3DSViewerSettings)
diff --git a/src/api/studio3d/q3dsviewersettings_p.h b/src/api/studio3d/q3dsviewersettings_p.h
index 8ff9394..a9f8c5b 100644
--- a/src/api/studio3d/q3dsviewersettings_p.h
+++ b/src/api/studio3d/q3dsviewersettings_p.h
@@ -69,6 +69,9 @@ public:
void setScaleMode(Q3DSViewerSettings::ScaleMode mode);
void setStereoMode(Q3DSViewerSettings::StereoMode mode);
void setStereoEyeSeparation(double separation);
+ void setStereoEyeRotation(double rotation);
+ void setStereoProgressiveEnabled(bool enabled);
+ void setSkipFramesInterval(int interval);
public:
Q3DSViewerSettings *q_ptr;
@@ -86,6 +89,9 @@ private:
Q3DSViewerSettings::ScaleMode m_scaleMode;
Q3DSViewerSettings::StereoMode m_stereoMode;
double m_stereoEyeSeparation;
+ double m_stereoEyeRotation;
+ bool m_stereoProgressiveEnabled;
+ int m_skipFramesInterval;
QSettings *m_savedSettings;
};
diff --git a/src/api/studio3d/studio3d.pro b/src/api/studio3d/studio3d.pro
index f0cd874..cfa8b71 100644
--- a/src/api/studio3d/studio3d.pro
+++ b/src/api/studio3d/studio3d.pro
@@ -65,3 +65,9 @@ SOURCES += \
../../foundation/qt/formatdiscovery.cpp
load(qt_module)
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+}
diff --git a/src/api/studio3dqml/plugins.qmltypes b/src/api/studio3dqml/plugins.qmltypes
index a1d360d..9fe0749 100644
--- a/src/api/studio3dqml/plugins.qmltypes
+++ b/src/api/studio3dqml/plugins.qmltypes
@@ -7,7 +7,7 @@ import QtQuick.tooling 1.2
// 'qmlplugindump -nonrelocatable QtStudio3D.OpenGL 2.5'
Module {
- dependencies: ["QtQuick 2.12"]
+ dependencies: []
Component {
name: "Q3DSDataInput"
prototype: "QObject"
@@ -145,6 +145,10 @@ Module {
name: "shaderCacheExported"
Parameter { name: "success"; type: "bool" }
}
+ Signal {
+ name: "shaderCacheLoadErrors"
+ Parameter { name: "errors"; type: "string" }
+ }
Method {
name: "setSource"
Parameter { name: "source"; type: "QUrl" }
@@ -235,6 +239,19 @@ Module {
revision: 1
Parameter { name: "binaryShaders"; type: "bool" }
}
+ Method {
+ name: "exportShaderCache"
+ revision: 2
+ Parameter { name: "shaderCacheFile"; type: "QUrl" }
+ Parameter { name: "binaryShaders"; type: "bool" }
+ Parameter { name: "compressionLevel"; type: "int" }
+ }
+ Method {
+ name: "exportShaderCache"
+ revision: 2
+ Parameter { name: "binaryShaders"; type: "bool" }
+ Parameter { name: "compressionLevel"; type: "int" }
+ }
}
Component {
name: "Q3DSPresentationItem"
@@ -242,9 +259,10 @@ Module {
prototype: "Q3DSPresentation"
exports: [
"QtStudio3D.OpenGL/Presentation 2.4",
- "QtStudio3D.OpenGL/Presentation 2.5"
+ "QtStudio3D.OpenGL/Presentation 2.5",
+ "QtStudio3D.OpenGL/Presentation 2.7"
]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 1, 2]
Property { name: "qmlChildren"; type: "QObject"; isList: true; isReadonly: true }
Method {
name: "appendQmlChildren"
@@ -328,7 +346,7 @@ Module {
"QtStudio3D.OpenGL/Studio3D 2.4",
"QtStudio3D.OpenGL/Studio3D 2.5"
]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 1]
Enum {
name: "EventIgnoreFlags"
values: {
@@ -346,6 +364,7 @@ Module {
Property { name: "ignoredEvents"; type: "EventIgnoreFlags" }
Property { name: "asyncInit"; revision: 1; type: "bool" }
Signal { name: "frameUpdate" }
+ Signal { name: "frameDraw" }
Signal {
name: "runningChanged"
Parameter { name: "initialized"; type: "bool" }
@@ -374,9 +393,10 @@ Module {
prototype: "QObject"
exports: [
"QtStudio3D.OpenGL/ViewerSettings 2.4",
- "QtStudio3D.OpenGL/ViewerSettings 2.5"
+ "QtStudio3D.OpenGL/ViewerSettings 2.5",
+ "QtStudio3D.OpenGL/ViewerSettings 2.7"
]
- exportMetaObjectRevisions: [0, 0]
+ exportMetaObjectRevisions: [0, 1, 2]
Enum {
name: "ShadeMode"
values: {
@@ -397,7 +417,9 @@ Module {
values: {
"StereoModeMono": 0,
"StereoModeTopBottom": 1,
- "StereoModeLeftRight": 2
+ "StereoModeLeftRight": 2,
+ "StereoModeAnaglyphRedCyan": 3,
+ "StereoModeAnaglyphGreenMagenta": 4
}
}
Property { name: "matteEnabled"; type: "bool" }
@@ -406,6 +428,8 @@ Module {
Property { name: "scaleMode"; type: "ScaleMode" }
Property { name: "stereoMode"; revision: 1; type: "StereoMode" }
Property { name: "stereoEyeSeparation"; revision: 1; type: "double" }
+ Property { name: "stereoProgressiveEnabled"; revision: 2; type: "bool" }
+ Property { name: "skipFramesInterval"; revision: 2; type: "int" }
Signal {
name: "matteEnabledChanged"
Parameter { name: "enabled"; type: "bool" }
@@ -434,6 +458,16 @@ Module {
name: "stereoEyeSeparationChanged"
Parameter { name: "separation"; type: "double" }
}
+ Signal {
+ name: "stereoProgressiveEnabledChanged"
+ revision: 2
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Signal {
+ name: "skipFramesIntervalChanged"
+ revision: 2
+ Parameter { name: "interval"; type: "int" }
+ }
Method {
name: "setMatteEnabled"
Parameter { name: "enabled"; type: "bool" }
@@ -459,6 +493,16 @@ Module {
Parameter { name: "separation"; type: "double" }
}
Method {
+ name: "setStereoProgressiveEnabled"
+ revision: 2
+ Parameter { name: "enabled"; type: "bool" }
+ }
+ Method {
+ name: "setSkipFramesInterval"
+ revision: 2
+ Parameter { name: "interval"; type: "int" }
+ }
+ Method {
name: "save"
Parameter { name: "group"; type: "string" }
Parameter { name: "organization"; type: "string" }
@@ -504,4 +548,180 @@ Module {
Parameter { type: "bool" }
}
}
+ Component {
+ name: "QQuickItem"
+ defaultProperty: "data"
+ prototype: "QObject"
+ Enum {
+ name: "Flags"
+ values: {
+ "ItemClipsChildrenToShape": 1,
+ "ItemAcceptsInputMethod": 2,
+ "ItemIsFocusScope": 4,
+ "ItemHasContents": 8,
+ "ItemAcceptsDrops": 16
+ }
+ }
+ Enum {
+ name: "TransformOrigin"
+ values: {
+ "TopLeft": 0,
+ "Top": 1,
+ "TopRight": 2,
+ "Left": 3,
+ "Center": 4,
+ "Right": 5,
+ "BottomLeft": 6,
+ "Bottom": 7,
+ "BottomRight": 8
+ }
+ }
+ Property { name: "parent"; type: "QQuickItem"; isPointer: true }
+ Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "resources"; type: "QObject"; isList: true; isReadonly: true }
+ Property { name: "children"; type: "QQuickItem"; isList: true; isReadonly: true }
+ Property { name: "x"; type: "double" }
+ Property { name: "y"; type: "double" }
+ Property { name: "z"; type: "double" }
+ Property { name: "width"; type: "double" }
+ Property { name: "height"; type: "double" }
+ Property { name: "opacity"; type: "double" }
+ Property { name: "enabled"; type: "bool" }
+ Property { name: "visible"; type: "bool" }
+ Property { name: "visibleChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
+ Property { name: "states"; type: "QQuickState"; isList: true; isReadonly: true }
+ Property { name: "transitions"; type: "QQuickTransition"; isList: true; isReadonly: true }
+ Property { name: "state"; type: "string" }
+ Property { name: "childrenRect"; type: "QRectF"; isReadonly: true }
+ Property { name: "anchors"; type: "QQuickAnchors"; isReadonly: true; isPointer: true }
+ Property { name: "left"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "right"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "horizontalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "top"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "bottom"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "verticalCenter"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "baseline"; type: "QQuickAnchorLine"; isReadonly: true }
+ Property { name: "baselineOffset"; type: "double" }
+ Property { name: "clip"; type: "bool" }
+ Property { name: "focus"; type: "bool" }
+ Property { name: "activeFocus"; type: "bool"; isReadonly: true }
+ Property { name: "activeFocusOnTab"; revision: 1; type: "bool" }
+ Property { name: "rotation"; type: "double" }
+ Property { name: "scale"; type: "double" }
+ Property { name: "transformOrigin"; type: "TransformOrigin" }
+ Property { name: "transformOriginPoint"; type: "QPointF"; isReadonly: true }
+ Property { name: "transform"; type: "QQuickTransform"; isList: true; isReadonly: true }
+ Property { name: "smooth"; type: "bool" }
+ Property { name: "antialiasing"; type: "bool" }
+ Property { name: "implicitWidth"; type: "double" }
+ Property { name: "implicitHeight"; type: "double" }
+ Property { name: "containmentMask"; revision: 11; type: "QObject"; isPointer: true }
+ Property { name: "layer"; type: "QQuickItemLayer"; isReadonly: true; isPointer: true }
+ Signal {
+ name: "childrenRectChanged"
+ Parameter { type: "QRectF" }
+ }
+ Signal {
+ name: "baselineOffsetChanged"
+ Parameter { type: "double" }
+ }
+ Signal {
+ name: "stateChanged"
+ Parameter { type: "string" }
+ }
+ Signal {
+ name: "focusChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "activeFocusChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "activeFocusOnTabChanged"
+ revision: 1
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "parentChanged"
+ Parameter { type: "QQuickItem"; isPointer: true }
+ }
+ Signal {
+ name: "transformOriginChanged"
+ Parameter { type: "TransformOrigin" }
+ }
+ Signal {
+ name: "smoothChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "antialiasingChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "clipChanged"
+ Parameter { type: "bool" }
+ }
+ Signal {
+ name: "windowChanged"
+ revision: 1
+ Parameter { name: "window"; type: "QQuickWindow"; isPointer: true }
+ }
+ Signal { name: "containmentMaskChanged"; revision: 11 }
+ Method { name: "update" }
+ Method {
+ name: "grabToImage"
+ revision: 4
+ type: "bool"
+ Parameter { name: "callback"; type: "QJSValue" }
+ Parameter { name: "targetSize"; type: "QSize" }
+ }
+ Method {
+ name: "grabToImage"
+ revision: 4
+ type: "bool"
+ Parameter { name: "callback"; type: "QJSValue" }
+ }
+ Method {
+ name: "contains"
+ type: "bool"
+ Parameter { name: "point"; type: "QPointF" }
+ }
+ Method {
+ name: "mapFromItem"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "mapToItem"
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "mapFromGlobal"
+ revision: 7
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method {
+ name: "mapToGlobal"
+ revision: 7
+ Parameter { type: "QQmlV4Function"; isPointer: true }
+ }
+ Method { name: "forceActiveFocus" }
+ Method {
+ name: "forceActiveFocus"
+ Parameter { name: "reason"; type: "Qt::FocusReason" }
+ }
+ Method {
+ name: "nextItemInFocusChain"
+ revision: 1
+ type: "QQuickItem*"
+ Parameter { name: "forward"; type: "bool" }
+ }
+ Method { name: "nextItemInFocusChain"; revision: 1; type: "QQuickItem*" }
+ Method {
+ name: "childAt"
+ type: "QQuickItem*"
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ }
+ }
}
diff --git a/src/api/studio3dqml/q3dsplugin.cpp b/src/api/studio3dqml/q3dsplugin.cpp
index 8a01141..5ab3dfa 100644
--- a/src/api/studio3dqml/q3dsplugin.cpp
+++ b/src/api/studio3dqml/q3dsplugin.cpp
@@ -40,6 +40,7 @@
#include "q3dsqmlsubpresentationsettings.h"
#include "q3dssceneelement.h"
#include "q3dsdatainput.h"
+#include "qtstudio3dversion.h"
QT_BEGIN_NAMESPACE
@@ -62,6 +63,18 @@ void Q3DSPlugin::registerTypes(const char *uri)
qmlRegisterType<Q3DSStudio3D, 1>(uri, 2, 5, "Studio3D");
qmlRegisterType<Q3DSViewerSettings, 1>(uri, 2, 5, "ViewerSettings");
qmlRegisterType<Q3DSPresentationItem, 1>(uri, 2, 5, "Presentation");
+ qmlRegisterRevision<Q3DSPresentation, 1>(uri, 2, 5);
+
+ // 2.7
+ qmlRegisterType<Q3DSPresentationItem, 2>(uri, 2, 7, "Presentation");
+ qmlRegisterType<Q3DSViewerSettings, 2>(uri, 2, 7, "ViewerSettings");
+ qmlRegisterRevision<Q3DSPresentation, 2>(uri, 2, 7);
+
+ // 2.8
+ qmlRegisterType<Q3DSViewerSettings, 3>(uri, 2, 8, "ViewerSettings");
+
+ // Automatically register the latest version
+ qmlRegisterModule(uri, ((QTSTUDIO3D_VERSION >> 16) & 0xff), ((QTSTUDIO3D_VERSION >> 8) & 0xff));
}
QT_END_NAMESPACE
diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp
index 7d63b30..52f20f7 100644
--- a/src/api/studio3dqml/q3dsrenderer.cpp
+++ b/src/api/studio3dqml/q3dsrenderer.cpp
@@ -197,27 +197,32 @@ void Q3DSRenderer::render()
// Don't render if the plugin is hidden; however, if hidden, but sure
// to process pending commands so we can be shown again.
if (m_initialized) {
+ bool updateAgain = false;
if (m_visibleFlag)
- draw();
+ updateAgain = draw();
else
processCommands();
- update(); // mark as dirty to ensure update again
+
+ if (updateAgain)
+ update(); // mark as dirty to ensure update again
}
}
/** Cause Qt3DS runtime to render content.
* Initializes GL and the runtime when called the first time.
*/
-void Q3DSRenderer::draw()
+bool Q3DSRenderer::draw()
{
+ bool ret = true;
if (m_runtime && m_runtime->IsInitialised() && m_window) {
if (m_initialized)
m_runtime->RestoreState();
- m_runtime->Render();
+ ret = m_runtime->Render();
m_runtime->SaveState();
m_window->resetOpenGLState();
}
+ return ret;
}
bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
@@ -230,6 +235,10 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
this, &Q3DSRenderer::presentationReady);
connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigPresentationLoaded,
this, &Q3DSRenderer::presentationLoaded);
+ connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigLoadShaderCacheErrors,
+ this, &Q3DSRenderer::shaderCacheLoadErrors);
+ connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigFrameDraw,
+ this, &Q3DSRenderer::frameDraw);
int theWidth = inFbo->width();
int theHeight = inFbo->height();
@@ -276,6 +285,8 @@ bool Q3DSRenderer::initializeRuntime(QOpenGLFramebufferObject *inFbo)
this, &Q3DSRenderer::customSignalEmitted);
connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigElementsCreated,
this, &Q3DSRenderer::elementsCreated);
+ connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigFrameDraw,
+ this, &Q3DSRenderer::frameDraw);
connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigMaterialsCreated,
this, &Q3DSRenderer::materialsCreated);
connect(m_runtime, &Q3DSViewer::Q3DSViewerApp::SigMeshesCreated,
@@ -344,6 +355,12 @@ void Q3DSRenderer::processCommands()
m_settings->setStereoMode(m_commands.m_stereoMode);
if (m_commands.m_stereoEyeSeparationChanged)
m_settings->setStereoEyeSeparation(m_commands.m_stereoEyeSeparation);
+ if (m_commands.m_stereoEyeRotationChanged)
+ m_settings->setStereoEyeRotation(m_commands.m_stereoEyeRotation);
+ if (m_commands.m_stereoProgressiveEnabledChanged)
+ m_settings->setStereoProgressiveEnabled(m_commands.m_stereoProgressiveEnabled);
+ if (m_commands.m_skipFramesIntervalChanged)
+ m_settings->setSkipFramesInterval(m_commands.m_skipFramesInterval);
if (m_commands.m_shadeModeChanged)
m_settings->setShadeMode(m_commands.m_shadeMode);
if (m_commands.m_matteColorChanged)
diff --git a/src/api/studio3dqml/q3dsrenderer_p.h b/src/api/studio3dqml/q3dsrenderer_p.h
index 0817494..084163e 100644
--- a/src/api/studio3dqml/q3dsrenderer_p.h
+++ b/src/api/studio3dqml/q3dsrenderer_p.h
@@ -76,11 +76,13 @@ Q_SIGNALS:
void requestResponse(const QString &elementPath, CommandType commandType, void *requestData);
void presentationReady();
void presentationLoaded();
+ void frameDraw();
void customSignalEmitted(const QString &elNmentPath, const QString &name);
void elementsCreated(const QStringList &elementPaths, const QString &error);
void materialsCreated(const QStringList &materialNames, const QString &error);
void meshesCreated(const QStringList &meshNames, const QString &error);
void dataOutputValueUpdated(const QString &name, const QVariant &newValue);
+ void shaderCacheLoadErrors(const QString &errors);
protected Q_SLOTS:
void handleRuntimeInitializedAsync();
@@ -89,7 +91,7 @@ protected:
static void onInitHandler(void *userData);
static void onUpdateHandler(void *userData);
bool initializeRuntime(QOpenGLFramebufferObject *inFbo);
- void draw();
+ bool draw();
void render() override;
void synchronize(QQuickFramebufferObject *inView) override;
void releaseRuntime();
diff --git a/src/api/studio3dqml/q3dsstudio3d.cpp b/src/api/studio3dqml/q3dsstudio3d.cpp
index f1e383f..3b0ac0d 100644
--- a/src/api/studio3dqml/q3dsstudio3d.cpp
+++ b/src/api/studio3dqml/q3dsstudio3d.cpp
@@ -114,6 +114,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlsignal Studio3D::frameDraw()
+ \since QtStudio3D.OpenGL 2.8
+
+ This signal is emitted each time a new image has been drawn.
+*/
+
+/*!
\qmlsignal Studio3D::frameUpdate()
This signal is emitted each time a frame has been rendered.
@@ -430,6 +437,8 @@ QQuickFramebufferObject::Renderer *Q3DSStudio3D::createRenderer() const
m_presentation->d_ptr, &Q3DSPresentationPrivate::handleMaterialsCreated);
connect(renderer, &Q3DSRenderer::meshesCreated,
m_presentation->d_ptr, &Q3DSPresentationPrivate::handleMeshesCreated);
+ connect(renderer, &Q3DSRenderer::shaderCacheLoadErrors,
+ m_presentation, &Q3DSPresentation::shaderCacheLoadErrors);
connect(renderer, &Q3DSRenderer::exitSlide,
m_presentation, &Q3DSPresentation::slideExited);
connect(renderer, &Q3DSRenderer::customSignalEmitted,
@@ -440,6 +449,8 @@ QQuickFramebufferObject::Renderer *Q3DSStudio3D::createRenderer() const
this, &Q3DSStudio3D::presentationLoaded);
connect(renderer, &Q3DSRenderer::presentationReady,
this, &Q3DSStudio3D::presentationReady);
+ connect(renderer, &Q3DSRenderer::frameDraw,
+ this, &Q3DSStudio3D::frameDraw);
return renderer;
}
@@ -461,7 +472,8 @@ bool Q3DSStudio3D::isRunning() const
Emit QML `runningChanged` and `frameUpdate` and signals.
This method is called every frame, and emits the `frameUpdate` signal every frame,
regardless of plugin visibility. This allows a hidden Qt3DSView to still process
- information every frame, even though the Renderer is not rendering.
+ information every frame, even though the Renderer is not rendering. You can use
+ frameDraw signal when you need to know when a new image has been drawn.
To prevent expensive onFrameUpdate handlers from being processed when hidden,
add an early return to the top like:
diff --git a/src/api/studio3dqml/q3dsstudio3d_p.h b/src/api/studio3dqml/q3dsstudio3d_p.h
index 1fd32fe..905ea35 100644
--- a/src/api/studio3dqml/q3dsstudio3d_p.h
+++ b/src/api/studio3dqml/q3dsstudio3d_p.h
@@ -65,6 +65,7 @@ class Q3DSStudio3D : public QQuickFramebufferObject
Q_PROPERTY(bool asyncInit READ asyncInit WRITE setAsyncInit NOTIFY asyncInitChanged REVISION 1)
public:
+
enum EventIgnoreFlag {
EnableAllEvents = 0,
IgnoreMouseEvents = 0x01,
@@ -104,6 +105,7 @@ public:
Q_SIGNALS:
void frameUpdate();
+ void frameDraw();
void runningChanged(bool initialized);
void errorChanged(const QString &error);
void ignoredEventsChanged();
diff --git a/src/api/studio3dqml/studio3dqml.pro b/src/api/studio3dqml/studio3dqml.pro
index df685fc..ac7f03d 100644
--- a/src/api/studio3dqml/studio3dqml.pro
+++ b/src/api/studio3dqml/studio3dqml.pro
@@ -34,3 +34,9 @@ OTHER_FILES += \
qmldir
load(qml_plugin)
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+}
diff --git a/src/dm/dm.pro b/src/dm/dm.pro
index 2e57f30..af4a846 100644
--- a/src/dm/dm.pro
+++ b/src/dm/dm.pro
@@ -56,3 +56,7 @@ HEADERS += \
systems/Qt3DSDMMetaDataValue.h \
systems/Qt3DSDMMetaData.h \
systems/Qt3DSDMWStrOpsImpl.h
+
+android {
+ CONFIG -= link_prl
+}
diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
index c1c0071..7f1a734 100644
--- a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
+++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.cpp
@@ -109,6 +109,7 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_Node L"Node"
#define QT3DS_WCHAR_T_Layer L"Layer"
#define QT3DS_WCHAR_T_Group L"Group"
+#define QT3DS_WCHAR_T_Signal L"Signal"
#define QT3DS_WCHAR_T_Model L"Model"
#define QT3DS_WCHAR_T_Light L"Light"
#define QT3DS_WCHAR_T_Camera L"Camera"
@@ -153,6 +154,8 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_positionv L"positionv"
#define QT3DS_WCHAR_T_pivotu L"pivotu"
#define QT3DS_WCHAR_T_pivotv L"pivotv"
+#define QT3DS_WCHAR_T_minfilter L"minfilter"
+#define QT3DS_WCHAR_T_magfilter L"magfilter"
#define QT3DS_WCHAR_T_subpresentation L"subpresentation"
#define QT3DS_WCHAR_T_iblprobe L"iblprobe"
#define QT3DS_WCHAR_T_shaderlighting L"shaderlighting"
@@ -244,6 +247,10 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_innertess L"innertess"
#define QT3DS_WCHAR_T_scalemode L"scalemode"
#define QT3DS_WCHAR_T_scaleanchor L"scaleanchor"
+#define QT3DS_WCHAR_T_dynamicresize L"dynamicresize"
+#define QT3DS_WCHAR_T_dynamicpaddingunits L"dynamicpaddingunits"
+#define QT3DS_WCHAR_T_dynamicpadding L"dynamicpadding"
+#define QT3DS_WCHAR_T_dynamiccombine L"dynamiccombine"
#define QT3DS_WCHAR_T_horzfields L"horzfields"
#define QT3DS_WCHAR_T_left L"left"
#define QT3DS_WCHAR_T_leftunits L"leftunits"
@@ -258,6 +265,7 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_heightunits L"heightunits"
#define QT3DS_WCHAR_T_bottom L"bottom"
#define QT3DS_WCHAR_T_bottomunits L"bottomunits"
+#define QT3DS_WCHAR_T_aoenabled L"aoenabled"
#define QT3DS_WCHAR_T_aostrength L"aostrength"
#define QT3DS_WCHAR_T_aodistance L"aodistance"
#define QT3DS_WCHAR_T_aosoftness L"aosoftness"
@@ -317,6 +325,8 @@ struct DataConstructor<SObjectRefType>
#define QT3DS_WCHAR_T_lightmapshadow L"lightmapshadow"
#define QT3DS_WCHAR_T_controlledproperty L"controlledproperty"
#define QT3DS_WCHAR_T_variants L"variants"
+#define QT3DS_WCHAR_T_ordered L"ordered"
+#define QT3DS_WCHAR_T_cullmode L"cullmode"
const wchar_t *ComposerObjectTypes::Convert(ComposerObjectTypes::Enum inType)
{
@@ -506,6 +516,7 @@ SComposerObjectDefinitions::SComposerObjectDefinitions(IDataCore &inCore, IMetaD
, m_Node(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Asset)
, m_Layer(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
, m_Group(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
+ , m_Signal(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
, m_Model(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
, m_Light(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
, m_Camera(inCore, inMetaData, inCore.CreateInstance(), m_Typed, m_Node)
diff --git a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
index ce49f07..22ef680 100644
--- a/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
+++ b/src/dm/systems/Qt3DSDMComposerTypeDefinitions.h
@@ -67,6 +67,7 @@ class IPropertySystem;
HANDLE_COMPOSER_OBJECT_TYPE(Node, ITERATE_COMPOSER_NODE_PROPERTIES) \
HANDLE_COMPOSER_OBJECT_TYPE(Layer, ITERATE_COMPOSER_LAYER_PROPERTIES) \
HANDLE_COMPOSER_OBJECT_TYPE(Group, ITERATE_COMPOSER_GROUP_PROPERTIES) \
+ HANDLE_COMPOSER_OBJECT_TYPE(Signal, ITERATE_COMPOSER_SIGNAL_PROPERTIES) \
HANDLE_COMPOSER_OBJECT_TYPE(Model, ITERATE_COMPOSER_MODEL_PROPERTIES) \
HANDLE_COMPOSER_OBJECT_TYPE(Light, ITERATE_COMPOSER_LIGHT_PROPERTIES) \
HANDLE_COMPOSER_OBJECT_TYPE(Camera, ITERATE_COMPOSER_CAMERA_PROPERTIES) \
@@ -122,6 +123,7 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY(orientation, m_Orientation, TDataStrPtr, L"Left Handed") \
HANDLE_COMPOSER_PROPERTY(boneid, m_BoneId, qt3ds::QT3DSI32, 0) \
HANDLE_COMPOSER_PROPERTY(ignoresparent, m_IgnoresParent, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(ordered, m_ordered, bool, false) \
HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"")
#define ITERATE_COMPOSER_MODEL_PROPERTIES \
@@ -144,6 +146,8 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY(positionv, m_PositionV, float, 0.f) \
HANDLE_COMPOSER_PROPERTY(pivotu, m_PivotU, float, 0.f) \
HANDLE_COMPOSER_PROPERTY(pivotv, m_PivotV, float, 0.f) \
+ HANDLE_COMPOSER_PROPERTY(minfilter, m_MinFilter, TDataStrPtr, L"LinearMipmapLinear") \
+ HANDLE_COMPOSER_PROPERTY(magfilter, m_MagFilter, TDataStrPtr, L"Linear") \
HANDLE_COMPOSER_PROPERTY(subpresentation, m_SubPresentation, TDataStrPtr, L"") \
HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"")
@@ -191,6 +195,7 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY(fresnelPower, m_FresnelPower, float, 0) \
HANDLE_COMPOSER_PROPERTY(vertexcolors, m_VertexColors, bool, false) \
HANDLE_COMPOSER_PROPERTY(transparencymode, m_TransparencyMode, TDataStrPtr, L"Default") \
+ HANDLE_COMPOSER_PROPERTY(cullmode, m_CullMode, TDataStrPtr, L"Back") \
HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"")
#define ITERATE_COMPOSER_REFERENCED_MATERIAL_PROPERTIES \
@@ -206,6 +211,10 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY_DUPLICATE(backgroundcolor, m_BackgroundColor, SFloat4, \
SFloat4(0, 0, 0, 1)) \
HANDLE_COMPOSER_PROPERTY(blendtype, m_BlendType, TDataStrPtr, L"Normal") \
+ HANDLE_COMPOSER_PROPERTY(dynamicresize, m_DynamicResize, bool, false) \
+ HANDLE_COMPOSER_PROPERTY(dynamicpaddingunits, m_DynamicPaddingUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(dynamicpadding, m_DynamicPadding, float, 0) \
+ HANDLE_COMPOSER_PROPERTY(dynamiccombine, m_DynamicCombine, bool, false) \
HANDLE_COMPOSER_PROPERTY(horzfields, m_HorizontalFieldValues, TDataStrPtr, L"Left/Width") \
HANDLE_COMPOSER_PROPERTY(left, m_Left, float, 0) \
HANDLE_COMPOSER_PROPERTY(leftunits, m_LeftUnits, TDataStrPtr, L"percent") \
@@ -220,6 +229,7 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY(heightunits, m_HeightUnits, TDataStrPtr, L"percent") \
HANDLE_COMPOSER_PROPERTY(bottom, m_Bottom, float, 0) \
HANDLE_COMPOSER_PROPERTY(bottomunits, m_BottomUnits, TDataStrPtr, L"percent") \
+ HANDLE_COMPOSER_PROPERTY(aoenabled, m_AoEnabled, bool, false) \
HANDLE_COMPOSER_PROPERTY(aostrength, m_AoStrength, float, 0) \
HANDLE_COMPOSER_PROPERTY(aodistance, m_AoDistance, float, 0) \
HANDLE_COMPOSER_PROPERTY(aosoftness, m_AoSoftness, float, 0) \
@@ -243,8 +253,12 @@ class IPropertySystem;
HANDLE_COMPOSER_PROPERTY_DUPLICATE(controlledproperty, m_ControlledProperty, TDataStrPtr, L"")
#define ITERATE_COMPOSER_GROUP_PROPERTIES \
+ HANDLE_COMPOSER_PROPERTY_DUPLICATE(ordered, m_ordered, bool, false) \
HANDLE_COMPOSER_PROPERTY_DUPLICATE(variants, m_variants, TDataStrPtr, L"") \
+#define ITERATE_COMPOSER_SIGNAL_PROPERTIES \
+ // Note: Signal doesn't contain any properties
+
#define ITERATE_COMPOSER_LIGHT_PROPERTIES \
HANDLE_COMPOSER_PROPERTY(lighttype, m_LightType, TDataStrPtr, L"Directional") \
HANDLE_COMPOSER_PROPERTY(scope, m_Scope, SObjectRefType, L"") \
@@ -791,6 +805,21 @@ struct SComposerObjectDefinition<ComposerObjectTypes::Group>
};
template <>
+struct SComposerObjectDefinition<ComposerObjectTypes::Signal>
+ : public SComposerBaseObjectDefinition<ComposerObjectTypes::Signal>
+{
+ SComposerObjectDefinition(IDataCore &inCore, IMetaData &inMetaData,
+ Qt3DSDMInstanceHandle inInstance,
+ SComposerObjectDefinition<ComposerObjectTypes::Typed> &inTyped,
+ SComposerObjectDefinition<ComposerObjectTypes::Node> &inNode)
+ : SComposerBaseObjectDefinition<ComposerObjectTypes::Signal>(inCore, inMetaData, inInstance)
+ {
+ Derive(inCore, inNode);
+ SetType(inCore, inTyped);
+ }
+};
+
+template <>
struct SComposerObjectDefinition<ComposerObjectTypes::Light>
: public SComposerBaseObjectDefinition<ComposerObjectTypes::Light>
{
diff --git a/src/dm/systems/Qt3DSDMMetaData.cpp b/src/dm/systems/Qt3DSDMMetaData.cpp
index 5e861cc..2af3f76 100644
--- a/src/dm/systems/Qt3DSDMMetaData.cpp
+++ b/src/dm/systems/Qt3DSDMMetaData.cpp
@@ -431,16 +431,24 @@ private:
public:
eastl::vector<qt3ds::render::dynamic::SCommand *> m_EffectCommands;
+ SMetaDataEffect m_effect;
+
void ClearEffectCommands()
{
for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx)
free(m_EffectCommands[idx]);
m_EffectCommands.clear();
}
- SMetaDataEffect ToEffect() const
+ SMetaDataEffect ToEffect()
+ {
+ m_effect = SMetaDataEffect(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
+ VecToCRef(m_EffectCommands));
+ return m_effect;
+ }
+ SMetaDataEffect *ToEffectPtr()
{
- return SMetaDataEffect(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
- VecToCRef(m_EffectCommands));
+ ToEffect();
+ return &m_effect;
}
};
@@ -458,6 +466,8 @@ public:
QT3DSU32 m_ShaderKey; ///< What does this shader contain ( e.g. specular, diffuse, ...)
QT3DSU32 m_LayerCount; ///< How much layers does this material have
+ SMetaDataCustomMaterial m_customMaterial;
+
void ClearEffectCommands()
{
for (QT3DSU32 idx = 0, end = m_EnumValueNames.size(); idx < end; ++idx) {
@@ -467,11 +477,18 @@ public:
m_CustomerMaterialCommands.clear();
}
- SMetaDataCustomMaterial ToMaterial() const
+ SMetaDataCustomMaterial ToMaterial()
{
- return SMetaDataCustomMaterial(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
- VecToCRef(m_CustomerMaterialCommands), m_HasTransparency,
- m_HasRefraction, m_AlwaysDirty, m_ShaderKey, m_LayerCount);
+ m_customMaterial =
+ SMetaDataCustomMaterial(m_Name, VecToCRef(m_Shaders), VecToCRef(m_Properties),
+ VecToCRef(m_CustomerMaterialCommands), m_HasTransparency,
+ m_HasRefraction, m_AlwaysDirty, m_ShaderKey, m_LayerCount);
+ return m_customMaterial;
+ }
+ SMetaDataCustomMaterial *ToMaterialPtr()
+ {
+ ToMaterial();
+ return &m_customMaterial;
}
};
@@ -529,6 +546,7 @@ public:
TStrInstanceMap m_CanonicalTypeToInstances;
TInstanceStrMap m_InstancesToCanonicalType;
TDerivationMap m_DerivationMap;
+ TInstanceStrMap m_InstanceToDynamicObject;
TCategoryMap m_Categories;
TNameCategoryMap m_NameToCategories;
@@ -1429,8 +1447,9 @@ public:
Qt3DSDMMetaDataPropertyHandle GetMetaDataProperty(Qt3DSDMInstanceHandle inInstance,
Qt3DSDMPropertyHandle inProperty) override
{
- Qt3DSDMPropertyDefinition propDef(m_DataCore->GetProperty(inProperty));
- return GetMetaDataProperty(inInstance, propDef.m_Name);
+ const Qt3DSDMPropertyDefinition &propDef = m_DataCore->GetProperty(inProperty);
+ return FindItemByName<Qt3DSDMMetaDataPropertyHandle>(inInstance, Intern(propDef.m_Name),
+ m_InstanceNameToProperties);
}
// Sets the value in the data core
virtual Option<SMetaDataPropertyInfo>
@@ -2998,10 +3017,27 @@ public:
}
}
+ static inline qt3ds::render::NVRenderFaces::Enum
+ ConvertToCullFace(const char8_t *inMode)
+ {
+ if (AreEqual(inMode, "Back"))
+ return qt3ds::render::NVRenderFaces::Back;
+ if (AreEqual(inMode, "Front"))
+ return qt3ds::render::NVRenderFaces::Front;
+ if (AreEqual(inMode, "All")) {
+ return qt3ds::render::NVRenderFaces::FrontAndBack;
+ } else {
+ QT3DS_ASSERT(false);
+ return qt3ds::render::NVRenderFaces::Back;
+ }
+ }
+
static inline qt3ds::render::NVRenderState::Enum ConvertRenderState(const char8_t *inState)
{
if (AreEqual(inState, "Stencil"))
return qt3ds::render::NVRenderState::StencilTest;
+ if (AreEqual(inState, "CullFace"))
+ return qt3ds::render::NVRenderState::CullFace;
else {
QT3DS_ASSERT(false);
// inFoundation.error( QT3DS_INVALID_PARAMETER, "Unsupported filter type %s, defaulting
@@ -3465,6 +3501,7 @@ public:
using namespace qt3ds::render::dynamic;
std::pair<TEffectMap::iterator, bool> theInserter =
m_EffectMap.insert(std::make_pair(Intern(inObjectName), SMetaDataEffectImpl()));
+ m_InstanceToDynamicObject.insert(make_pair(inInstance, Intern(inObjectName)));
/*if ( inStream.MoveToFirstChild( "Effect" ) == false )
{
outWarnings.push_back( SMetaDataLoadWarning( MetaDataLoadWarningType::Unknown,
@@ -3879,6 +3916,7 @@ public:
// Remove the previous custom material entry so that the new shader code is used
m_CustomMaterials.erase(Intern(inObjectName));
+ m_InstanceToDynamicObject.insert(make_pair(inInstance, Intern(inObjectName)));
std::pair<TCustomMaterialMap::iterator, bool> theInserter = m_CustomMaterials.insert(
std::make_pair(Intern(inObjectName), SMetaDataCustomMaterialImpl()));
@@ -4028,10 +4066,48 @@ public:
theDstBlendFuc));
// if we have blending we have transparency
theMaterial.m_HasTransparency = true;
+ } else if (AreEqual("Depth", inStream.GetNarrowElementName())) {
+ const char8_t *depthFuncStr = "";
+ const char8_t *depthMaskStr = "";
+ inStream.Att("func", depthFuncStr);
+ inStream.Att("mask", depthMaskStr);
+
+ qt3ds::render::NVRenderBoolOp::Enum depthFunc
+ = ParseBoolOp(depthFuncStr);
+ bool depthMask = true;
+
+ if (AreEqual("false", depthMaskStr))
+ depthMask = false;
+
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyDepth(depthFunc, depthMask));
} else if (AreEqual("RenderState",
inStream.GetNarrowElementName())) {
- // UdoL Todo: add this one
- }
+ const char8_t *name = "";
+ inStream.Att("name", name);
+ const char8_t *value = "";
+ inStream.Att("value", value);
+ // find the param and the type.
+ bool theStateEnable = false;
+ qt3ds::render::NVRenderState::Enum theState
+ = ConvertRenderState(name);
+ if (AreEqual("true", value))
+ theStateEnable = true;
+
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyRenderState(theState, theStateEnable));
+ } else if (AreEqual("Culling",
+ inStream.GetNarrowElementName())) {
+ const char8_t *cullMode = "";
+ inStream.Att("mode", cullMode);
+
+ qt3ds::render::NVRenderFaces::Enum face =
+ ConvertToCullFace(cullMode);
+
+ // this will setup blending
+ theMaterial.m_CustomerMaterialCommands.push_back(
+ new SApplyCulling(face));
+ }
}
}
// add the render command as last thing in the pass, it is a render
@@ -4146,6 +4222,25 @@ public:
return Empty();
}
+ virtual SMetaDataDynamicObject *GetDynamicObjectByInstance(Qt3DSDMInstanceHandle inInstance)
+ {
+ auto iter = m_InstanceToDynamicObject.find(inInstance);
+ if (iter != m_InstanceToDynamicObject.end()) {
+ TCharPtr theName(iter->second);
+ auto matIter = m_CustomMaterials.find(theName);
+ if (matIter != m_CustomMaterials.end()) {
+ SMetaDataCustomMaterialImpl &matImpl = matIter->second;
+ return matImpl.ToMaterialPtr();
+ }
+ auto effectIter = m_EffectMap.find(theName);
+ if (effectIter != m_EffectMap.end()) {
+ SMetaDataEffectImpl &effectImpl = effectIter->second;
+ return effectImpl.ToEffectPtr();
+ }
+ }
+ return nullptr;
+ }
+
////////////////////////////////////////////////////////////////////////////////////
// Undo/Redo
void SetConsumer(TTransactionConsumerPtr inConsumer) override { m_Consumer = inConsumer; }
diff --git a/src/dm/systems/Qt3DSDMMetaData.h b/src/dm/systems/Qt3DSDMMetaData.h
index a35002b..e81223c 100644
--- a/src/dm/systems/Qt3DSDMMetaData.h
+++ b/src/dm/systems/Qt3DSDMMetaData.h
@@ -363,6 +363,7 @@ public:
qt3ds::foundation::IInStream &inStream) = 0;
virtual Option<SMetaDataCustomMaterial> GetMaterialBySourcePath(const char *inSourcePath) = 0;
virtual Option<SMetaDataCustomMaterial> GetMaterialByName(const char *inName) = 0;
+ virtual SMetaDataDynamicObject *GetDynamicObjectByInstance(Qt3DSDMInstanceHandle inInstance) = 0;
////////////////////////////////////////////////////////////////////////////////////
// Undo/Redo
diff --git a/src/dm/systems/Qt3DSDMSlideCore.h b/src/dm/systems/Qt3DSDMSlideCore.h
index 6e32a56..743774f 100644
--- a/src/dm/systems/Qt3DSDMSlideCore.h
+++ b/src/dm/systems/Qt3DSDMSlideCore.h
@@ -34,9 +34,36 @@
#include "HandleSystemBase.h"
#include "Qt3DSDMStringTable.h"
#include "Qt3DSDMDataCore.h"
+#include <QtCore/qdebug.h>
+
namespace qt3dsdm {
-typedef std::pair<Qt3DSDMInstanceHandle, Qt3DSDMPropertyHandle> TInstancePropertyPair;
+
+struct TInstancePropertyPair {
+ int first;
+ int second;
+ TInstancePropertyPair() : first(0), second(0) {
+
+ }
+ TInstancePropertyPair(int _first, int _second) : first(_first), second(_second) {
+
+ }
+ TInstancePropertyPair(const TInstancePropertyPair &pa)
+ : first(pa.first), second(pa.second)
+ {
+
+ }
+ friend bool operator == (const TInstancePropertyPair& pa1, const TInstancePropertyPair& pa2)
+ {
+ return pa1.first == pa2.first && pa1.second == pa2.second;
+ }
+ friend QDebug operator << (QDebug &debug, const TInstancePropertyPair &pair)
+ {
+ debug << pair.first << " " << pair.second;
+ return debug;
+ }
+};
+
typedef std::vector<TInstancePropertyPair> TInstancePropertyPairList;
// instance,property,value
@@ -236,4 +263,20 @@ public:
typedef std::shared_ptr<ISlideCore> TSlideCorePtr;
}
+namespace std {
+
+template<> struct hash<qt3dsdm::TInstancePropertyPair >
+{
+ typedef qt3dsdm::TInstancePropertyPair argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const& pa) const
+ {
+ result_type const h1 ( std::hash<int>{}(pa.first) );
+ result_type const h2 ( std::hash<int>{}(pa.second) );
+ return h1 ^ (h2 << 1);
+ }
+};
+
+}
+
#endif
diff --git a/src/dm/systems/SlideSystem.cpp b/src/dm/systems/SlideSystem.cpp
index c24e2c7..0a4248e 100644
--- a/src/dm/systems/SlideSystem.cpp
+++ b/src/dm/systems/SlideSystem.cpp
@@ -139,7 +139,7 @@ void SetEntryValueIfNotReferenced(const TSlideEntry &inEntry,
else
inDestCore->ForceSetInstancePropertyValue(inDestSlide, get<0>(inEntry), get<1>(inEntry),
get<2>(inEntry));
- CopyAnimationIfExist(inSource, inDestSlide, make_pair(get<0>(inEntry), get<1>(inEntry)),
+ CopyAnimationIfExist(inSource, inDestSlide, TInstancePropertyPair(get<0>(inEntry), get<1>(inEntry)),
inPropertySystem, inAnimationCore);
}
@@ -614,7 +614,8 @@ void SSlideSystem::UnlinkProperty(Qt3DSDMInstanceHandle inInstance, Qt3DSDMPrope
std::placeholders::_1,
inInstance, inProperty, theValue));
do_all(theChildren,
- std::bind(CopyAnimationIfExist, theSlide, std::placeholders::_1, make_pair(inInstance, inProperty),
+ std::bind(CopyAnimationIfExist, theSlide, std::placeholders::_1,
+ TInstancePropertyPair(inInstance, inProperty),
m_PropertySystem, m_AnimationCore));
}
GetSignalSender()->SendPropertyUnlinked(theSlide, inInstance, inProperty);
diff --git a/src/dm/systems/cores/DataCoreProducer.cpp b/src/dm/systems/cores/DataCoreProducer.cpp
index 5c3cc92..e74f95e 100644
--- a/src/dm/systems/cores/DataCoreProducer.cpp
+++ b/src/dm/systems/cores/DataCoreProducer.cpp
@@ -109,19 +109,6 @@ void CDataCoreProducer::GetInstancesDerivedFrom(TInstanceHandleList &outInstance
m_Data->GetInstancesDerivedFrom(outInstances, inParentHandle);
}
-struct ClearInstanceParentCacheTransaction : public ITransaction
-{
- const CDataModelInstance &m_Instance;
- ClearInstanceParentCacheTransaction(const char *inFile, int inLine,
- const CDataModelInstance &inst)
- : ITransaction(inFile, inLine)
- , m_Instance(inst)
- {
- }
- void Do() override { m_Instance.ClearParentCache(); }
- void Undo() override { m_Instance.ClearParentCache(); }
-};
-
void CDataCoreProducer::DeriveInstance(Qt3DSDMInstanceHandle inInstance,
Qt3DSDMInstanceHandle inParent)
{
@@ -134,9 +121,6 @@ void CDataCoreProducer::DeriveInstance(Qt3DSDMInstanceHandle inInstance,
make_pair(inParent.GetHandleValue(),
CSimpleDataCore::GetInstanceNF(inParent, m_Data->m_Objects)),
theInstance->m_Parents);
- m_Consumer->OnTransaction(std::static_pointer_cast<ITransaction>(
- std::make_shared<ClearInstanceParentCacheTransaction>(__FILE__, __LINE__,
- *theInstance)));
}
GetDataCoreSender()->SignalInstanceDerived(inInstance, inParent);
}
diff --git a/src/dm/systems/cores/SimpleDataCore.h b/src/dm/systems/cores/SimpleDataCore.h
index 2664dab..fd4e51a 100644
--- a/src/dm/systems/cores/SimpleDataCore.h
+++ b/src/dm/systems/cores/SimpleDataCore.h
@@ -101,7 +101,6 @@ public:
typedef std::unordered_map<int, bool> TInstanceParentMap;
TInstancePairList m_Parents;
- mutable TInstanceParentMap m_CachedParents;
// Properties specific to this class
TIntList m_Properties;
TPropertyPairHash m_PropertyValues;
@@ -128,33 +127,20 @@ public:
m_PropertyValues.insert(*iter);
}
- void ClearParentCache() const { m_CachedParents.clear(); }
+ void ClearParentCache() const { }
bool IsDerivedFrom(Qt3DSDMInstanceHandle inParent) const
{
- std::pair<TInstanceParentMap::iterator, bool> theQueryResult =
- m_CachedParents.insert(std::make_pair(inParent.GetHandleValue(), false));
- // If the insert failed, returned what the hashtable already had in it
- if (theQueryResult.second == false)
- return theQueryResult.first->second;
-
- // Else find a valid answer
if (m_Parents.find(inParent.GetHandleValue()) != m_Parents.end()) {
- theQueryResult.first->second = true;
+ return true;
} else {
for (TInstancePairList::const_iterator iter = m_Parents.begin(), end = m_Parents.end();
iter != end; ++iter) {
- if (iter->second->IsDerivedFrom(inParent)) {
- theQueryResult.first->second = true;
- break;
- }
+ if (iter->second->IsDerivedFrom(inParent))
+ return true;
}
}
-
- // Note that we inserted false to begin with. This means that
- // we can return the insert result here safely as if it wasn't
- // supposed to be false, we would have set it above.
- return theQueryResult.first->second;
+ return false;
}
void RemoveCachedValues()
diff --git a/src/dm/systems/cores/SimpleSlideCore.h b/src/dm/systems/cores/SimpleSlideCore.h
index effa3bd..6c33422 100644
--- a/src/dm/systems/cores/SimpleSlideCore.h
+++ b/src/dm/systems/cores/SimpleSlideCore.h
@@ -36,30 +36,11 @@
#include <unordered_map>
#include <QtCore/qdebug.h>
-namespace std {
-
-template<> struct hash<std::pair<int,int> >
-{
- typedef std::pair<int,int> argument_type;
- typedef std::size_t result_type;
- result_type operator()(std::pair<int,int> const& pa) const
- {
- result_type const h1 ( std::hash<int>{}(pa.first) );
- result_type const h2 ( std::hash<int>{}(pa.second) );
- return h1 ^ (h2 << 1);
- }
-};
-
-}
-
namespace qt3dsdm {
-// The first revision of this
-typedef std::pair<int, int> TSlideInstancePropertyPair;
+typedef TInstancePropertyPair TSlideInstancePropertyPair;
typedef std::unordered_map<TSlideInstancePropertyPair, SInternValue > TSlideEntryHash;
-using std::make_pair;
-
// Abstract access to these objects a little bit because in the future we are going to
// reorganize the data such that getting a defined set of properties for a single instance is
// very fast.
@@ -111,7 +92,7 @@ struct SSlide : public CHandleObject
SInternValue *GetInstancePropertyValue(Qt3DSDMInstanceHandle inInstance,
Qt3DSDMPropertyHandle inProperty) const
{
- TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue());
+ const TSlideInstancePropertyPair theKey(inInstance.GetHandleValue(), inProperty.GetHandleValue());
TSlideEntryHash::const_iterator find(m_Properties.find(theKey));
if (find != m_Properties.end())
return const_cast<SInternValue *>(&find->second);
@@ -126,7 +107,7 @@ struct SSlide : public CHandleObject
theIter != theEnd; ++theIter) {
if (theIter->first.first == inInstance)
outProperties.push_back(
- make_pair(theIter->first.second, theIter->second.GetValue()));
+ std::make_pair(theIter->first.second, theIter->second.GetValue()));
}
}
@@ -161,7 +142,7 @@ struct SSlide : public CHandleObject
{
for (size_t idx = 0, end = inList.size(); idx < end; ++idx)
m_Properties.erase(
- std::pair<int, int>(std::get<0>(inList[idx]), std::get<1>(inList[idx])));
+ TSlideInstancePropertyPair(std::get<0>(inList[idx]), std::get<1>(inList[idx])));
}
void InsertSlideEntries(const TSlideEntryList &inList, IStringTable &inStringTable)
diff --git a/src/dm/systems/cores/SlideCoreProducer.cpp b/src/dm/systems/cores/SlideCoreProducer.cpp
index 75b7c69..4177b69 100644
--- a/src/dm/systems/cores/SlideCoreProducer.cpp
+++ b/src/dm/systems/cores/SlideCoreProducer.cpp
@@ -203,7 +203,6 @@ struct HashMapDataValueInsertTransaction
}
void Do() override
{
- std::pair<int, int> theKey = m_Value.first;
SValue theTempValue = m_Value.second.GetValue();
TDataStrPtr theStrPtr;
if (GetValueType(theTempValue) == DataModelDataType::String) {
@@ -223,7 +222,7 @@ inline void CSlideCoreProducer::DoForceSetInstancePropertyValue(Qt3DSDMSlideHand
SInternValue theNewValue(inValue, m_Data->GetStringTable());
SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty));
- std::pair<int, int> theKey(inHandle, inProperty);
+ const TInstancePropertyPair theKey(inHandle, inProperty);
SlideInstancePropertyKey mergeMapKey(inSlide, inHandle, inProperty);
TSlidePropertyMergeMap::iterator iter = m_PropertyMergeMap.find(mergeMapKey);
if (iter != m_PropertyMergeMap.end()) {
@@ -322,7 +321,7 @@ inline void ClearValueWithTransactions(TTransactionConsumerPtr inConsumer,
SInternValue *theCurrentValue(theSlide->GetInstancePropertyValue(inHandle, inProperty));
if (theCurrentValue) {
SValue theValue(theCurrentValue->GetValue());
- std::pair<int, int> theKey(inHandle, inProperty);
+ TInstancePropertyPair theKey(inHandle, inProperty);
CreateHashMapEraseTransaction(__FILE__, __LINE__, inConsumer,
std::make_pair(theKey, *theCurrentValue),
theSlide->m_Properties);
diff --git a/src/engine/Qt3DSRenderRuntimeBinding.cpp b/src/engine/Qt3DSRenderRuntimeBinding.cpp
index fc413f6..3f4b662 100644
--- a/src/engine/Qt3DSRenderRuntimeBinding.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBinding.cpp
@@ -206,6 +206,11 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
return m_Presentation->m_preferKTX;
}
+ bool flipCompressedTextures() const override
+ {
+ return m_Presentation->m_flipCompressedTextures;
+ }
+
// Update really just adds objects to the dirty set
bool Update()
{
@@ -249,6 +254,24 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
Q3DStudio::UVariant value;
if (theElement.GetAttribute(ATTRIBUTE_SUBPRESENTATION, value))
subs.push_back(m_Context->GetStringTable().HandleToStr(value.m_StringHandle));
+ } else if (theTranslator && theTranslator->GetUIPType()
+ == GraphObjectTypes::CustomMaterial) {
+ // Add custom material strings to the subpresentation list since any string
+ // property could be a texture with a subpresentation source.
+ // Non-subpresentation strings are filtered out by the function caller.
+ int numProperties = theElement.GetNumProperties();
+ for (int i = 0; i < numProperties; ++i) {
+ auto property = theElement.GetPropertyByIndex(i);
+ if (property.hasValue()) {
+ auto value = property.getValue();
+ if (value.first.type() == ATTRIBUTETYPE_STRING) {
+ auto stringValue = m_Context->GetStringTable().HandleToStr(
+ value.second->m_StringHandle);
+ if (stringValue.IsValid())
+ subs.push_back(stringValue);
+ }
+ }
+ }
}
}
}
@@ -270,10 +293,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
TransferDirtyProperties();
m_LastRenderViewport = m_Context->GetRenderList().GetViewport();
if (m_Presentation && m_Presentation->m_Scene) {
- NVRenderRect theViewportSize(m_LastRenderViewport);
- return m_Presentation->m_Scene->PrepareForRender(
- QT3DSVec2(QT3DSF32(theViewportSize.m_Width), QT3DSF32(theViewportSize.m_Height)),
- *m_Context);
+ return m_Presentation->m_Scene->PrepareForRender(*m_Context);
}
return false;
}
@@ -683,7 +703,7 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
nvvector<SGraphObject *>::iterator end = vec.end();
while (it != end) {
if ((*it)->m_Type == type)
- callable(static_cast<T*>(*it));
+ callable(static_cast<T*>(*it), preferKtx());
++it;
}
}
@@ -691,12 +711,14 @@ struct Qt3DSRenderScene : public Q3DStudio::IScene
void PostLoadStep()
{
IBufferManager &mgr = m_Context->GetBufferManager();
- forAllObjects<SImage>(m_GraphObjectList, GraphObjectTypes::Image, [&mgr](SImage *image){
+ forAllObjects<SImage>(m_GraphObjectList, GraphObjectTypes::Image,
+ [&mgr](SImage *image, bool preferKtx){
if (image->m_ImagePath.IsValid() && qt3ds::runtime::isImagePath(
image->m_ImagePath.c_str())) {
const bool ibl = image->m_MappingMode == ImageMappingModes::LightProbe;
- image->m_LoadedTextureData = mgr.CreateReloadableImage(image->m_ImagePath,
- false, ibl);
+ const auto resolved = IBufferManager::resolveImagePath(
+ QString::fromLatin1(image->m_ImagePath.c_str()), preferKtx);
+ image->m_LoadedTextureData = mgr.CreateReloadableImage(resolved, false, ibl);
image->m_LoadedTextureData->m_callbacks.push_back(image);
}
});
@@ -752,8 +774,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
Q3DStudio::SPickFrame m_PickFrame;
NVDataRef<QT3DSU8> m_StrTableData;
// The boolean is to mark transparent images and ibl images
- nvvector<eastl::pair<CRegisteredString, eastl::pair<bool, bool>>> m_SourcePaths;
- eastl::hash_set<CRegisteredString> m_SourcePathSet;
+ nvvector<eastl::pair<QString, eastl::pair<bool, bool>>> m_SourcePaths;
+ QSet<QString> m_SourcePathSet;
Qt3DSRenderScene *m_LastRenderedScene;
Q3DStudio::IWindowSystem &m_WindowSystem;
@@ -872,6 +894,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
Q3DStudio::IScriptBridge &inBridge,
const qt3ds::Q3DSVariantConfig &variantConfig) override
{
+ QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
+ "Binding: LoadScene")
// We have to initialize the tags late so that we can load flow data before adding anything
// to the string table.
Qt3DSTranslator::InitializePointerTags(m_Context->m_RenderContext->GetStringTable());
@@ -898,7 +922,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
m_Context->m_Context->GetCustomMaterialSystem(),
m_Context->m_Context->GetDynamicObjectSystem(),
m_Context->m_Context->GetPathManager(), &theResolver,
- variantConfig, false);
+ variantConfig, false, inPresentation->getUIPVersion());
if (!theScene->m_Presentation) {
QT3DS_ASSERT(false);
return nullptr;
@@ -907,55 +931,54 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
NVConstDataRef<eastl::string> theSourcePathData(inParser->GetSourcePaths());
const QVector<QString> slideSourcePaths = inParser->GetSlideSourcePaths();
IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
+
// List of image paths to be loaded in parallel at the end.
- eastl::vector<CRegisteredString> theSourcePathList;
- eastl::vector<CRegisteredString> iblList;
+ QVector<QString> theSourcePathList;
+ QVector<QString> iblList;
+
+ const auto preferKtx = theScene->m_Presentation->m_preferKTX;
+ const auto flipCompressed = theScene->m_Presentation->m_flipCompressedTextures;
+ const auto contextType = m_Context->m_Context->GetRenderContext().GetRenderContextType();
+
for (QT3DSU32 idx = 0, end = theSourcePathData.size(); idx < end; ++idx) {
const eastl::string &theValue = theSourcePathData[idx];
- CRegisteredString theSourcePath =
- m_Context->m_CoreContext->GetStringTable().RegisterStr(theValue.c_str());
+ QString sourcePath = QString::fromLatin1(theValue.c_str());
size_t theValueSize = theValue.size();
if (theValueSize > 3) {
- CRegisteredString theObjectPath = theSourcePath;
- if (qt3ds::runtime::isImagePath(theValue.c_str())) {
+ if (qt3ds::runtime::isImagePath(sourcePath)) {
// load only images not on any slide
+ const QString resolvedPath
+ = IBufferManager::resolveImagePath(sourcePath, preferKtx);
if (!theManager.isReloadableResourcesEnabled() ||
- !slideSourcePaths.contains(QString::fromLatin1(theValue.c_str()))) {
- theManager.SetImageTransparencyToFalseIfNotSet(theObjectPath);
- bool ibl = inParser->isIblImage(theObjectPath.c_str());
- bool transparent = theManager.GetImageHasTransparency(theObjectPath);
- if (m_SourcePathSet.insert(theSourcePath).second) {
-
- m_SourcePaths.push_back(eastl::make_pair(theSourcePath,
+ !slideSourcePaths.contains(sourcePath)) {
+ theManager.SetImageTransparencyToFalseIfNotSet(resolvedPath);
+ bool ibl = inParser->isIblImage(theValue);
+ bool transparent = theManager.GetImageHasTransparency(resolvedPath);
+ if (!m_SourcePathSet.contains(resolvedPath)) {
+ m_SourcePaths.push_back(eastl::make_pair(resolvedPath,
eastl::make_pair(transparent, ibl)));
+ m_SourcePathSet.insert(resolvedPath);
}
if (ibl)
- iblList.push_back(theObjectPath);
+ iblList.push_back(resolvedPath);
else
- theSourcePathList.push_back(theObjectPath);
+ theSourcePathList.push_back(resolvedPath);
}
} else if (theValue.find(".mesh") != eastl::string::npos) {
- theManager.LoadMesh(theObjectPath);
+ theManager.LoadMesh(theManager.GetStringTable().RegisterStr(theValue));
}
}
}
// Fire off parallel loading of the source paths
- QT3DSU64 imageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
- toConstDataRef(theSourcePathList.data(), theSourcePathList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(),
- theScene->m_Presentation->m_preferKTX, false);
- QT3DSU64 iblImageBatchId = m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
- toConstDataRef(iblList.data(), iblList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(),
- theScene->m_Presentation->m_preferKTX, true);
- m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded(
- static_cast<TImageBatchId>(imageBatchId));
- m_Context->m_Context->GetImageBatchLoader().BlockUntilLoaded(
- static_cast<TImageBatchId>(iblImageBatchId));
+ auto &batchLoader = m_Context->m_Context->GetImageBatchLoader();
+ QT3DSU64 imageBatchId = batchLoader.LoadImageBatch(theSourcePathList, {}, nullptr,
+ contextType, false, flipCompressed);
+ QT3DSU64 iblImageBatchId = batchLoader.LoadImageBatch(iblList, {}, nullptr, contextType,
+ true, flipCompressed);
+ batchLoader.BlockUntilLoaded(static_cast<TImageBatchId>(imageBatchId));
+ batchLoader.BlockUntilLoaded(static_cast<TImageBatchId>(iblImageBatchId));
theIScene = QT3DS_NEW(m_Context->GetAllocator(),
Qt3DSRenderScene)(*m_Context, *m_Context->m_Context, *theScene);
@@ -1006,7 +1029,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
qt3ds::render::ILoadedBuffer &inData) override
{
QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
- "Load Scene Graph Stage 1")
+ "Binding: Load Scene Graph Stage 1")
NVDataRef<QT3DSU8> theLoadedData(inData.Data());
SDataReader theReader(theLoadedData.begin(), theLoadedData.end());
@@ -1064,7 +1087,7 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
size_t inElementMemoryOffset, Q3DStudio::IScriptBridge &inBridge) override
{
QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
- "Load Scene Graph Stage 2")
+ "Binding: Load Scene Graph Stage 2")
QT3DSU32 theSceneIndex = QT3DS_MAX_U32;
SSceneLoadData *theScene;
{
@@ -1097,29 +1120,24 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
{
QT3DS_ASSERT(m_Context->m_Context.mPtr);
// this means graphics have been initialized
- eastl::string theSourcePathStr;
IBufferManager &theManager(m_Context->m_Context->GetBufferManager());
- nvvector<CRegisteredString> imagePathList(m_Context->GetAllocator(),
- "imagePathList");
- nvvector<CRegisteredString> iblImagePathList(m_Context->GetAllocator(),
- "iblImagePathList");
+ QVector<QString> imagePathList;
+ QVector<QString> iblImagePathList;
for (QT3DSU32 idx = 0, end = m_SourcePaths.size(); idx < end; ++idx) {
- theSourcePathStr.assign(m_SourcePaths[idx].first);
+ QString theSourcePathStr = m_SourcePaths[idx].first;
bool hasTransparency = m_SourcePaths[idx].second.first;
bool isIbl = m_SourcePaths[idx].second.second;
- if (theSourcePathStr.size() > 4) {
- CRegisteredString theObjectPath = m_SourcePaths[idx].first;
- if (qt3ds::runtime::isImagePath(theSourcePathStr.c_str())) {
+ if (theSourcePathStr.length() > 4) {
+ if (qt3ds::runtime::isImagePath(theSourcePathStr)) {
theManager.SetImageHasTransparency(
- theObjectPath, hasTransparency,
- theManager.GetImageHasOpaquePixels(theObjectPath));
+ theSourcePathStr, hasTransparency,
+ theManager.GetImageHasOpaquePixels(theSourcePathStr));
if (isIbl)
- iblImagePathList.push_back(theObjectPath);
+ iblImagePathList.push_back(theSourcePathStr);
else
- imagePathList.push_back(theObjectPath);
- } else {
- if (theSourcePathStr.find(".mesh") != eastl::string::npos)
- theManager.LoadMesh(theObjectPath);
+ imagePathList.push_back(theSourcePathStr);
+ } else if (theSourcePathStr.contains(QStringLiteral(".mesh"))) {
+ theManager.LoadMesh(theManager.GetStringTable().RegisterStr(theSourcePathStr));
}
}
}
@@ -1133,23 +1151,18 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
}
{
+ auto contextType = m_Context->m_Context->GetRenderContext().GetRenderContextType();
QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
- "Initial Batch Image Load")
-
- m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
- toConstDataRef(imagePathList.data(), imagePathList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(), pktx, false);
- m_Context->m_Context->GetImageBatchLoader().LoadImageBatch(
- toConstDataRef(iblImagePathList.data(), iblImagePathList.size()),
- CRegisteredString(), nullptr, m_Context->m_Context->GetRenderContext()
- .GetRenderContextType(), pktx, true);
+ "Binding: Initial Batch Image Load")
+ auto &batchLoader = m_Context->m_Context->GetImageBatchLoader();
+ batchLoader.LoadImageBatch(imagePathList, {}, nullptr, contextType, pktx, false);
+ batchLoader.LoadImageBatch(iblImagePathList, {}, nullptr, contextType, pktx, true);
}
{
QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
- "Initialize Scenes")
+ "Binding: Initialize Scenes")
for (QT3DSU32 idx = 0, end = m_LoadingScenes.size(); idx < end; ++idx) {
SSceneLoadData &theScene = *m_LoadingScenes[idx];
// m_Context->m_Foundation->error( QT3DS_WARN, "Finalizing scene %d", (int)idx+1 );
@@ -1206,16 +1219,19 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
void LoadQmlStreamerPlugin(const char *inAssetIDString) override
{
- qt3ds::render::IOffscreenRenderer *theOffscreenRenderer =
- QT3DS_NEW(m_Context->GetAllocator(),
- Q3DSQmlRender)(*m_Context->m_Context, inAssetIDString);
- if (theOffscreenRenderer) {
- qt3ds::foundation::CRegisteredString theAssetString =
- m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString);
- m_Context->m_Context->GetOffscreenRenderManager().RegisterOffscreenRenderer(
- SOffscreenRendererKey(theAssetString), *theOffscreenRenderer);
-
- m_RenderPlugins.push_back(make_pair(theAssetString, 0));
+ qt3ds::foundation::CRegisteredString theAssetString =
+ m_Context->m_CoreContext->GetStringTable().RegisterStr(inAssetIDString);
+ auto &orm = m_Context->m_Context->GetOffscreenRenderManager();
+ const SOffscreenRendererKey offscreenRendererKey(theAssetString);
+ if (!orm.GetOffscreenRenderer(offscreenRendererKey)) {
+ qt3ds::render::IOffscreenRenderer *theOffscreenRenderer =
+ QT3DS_NEW(m_Context->GetAllocator(),
+ Q3DSQmlRender)(*m_Context->m_Context, inAssetIDString);
+ if (theOffscreenRenderer) {
+ orm.RegisterOffscreenRenderer(
+ SOffscreenRendererKey(theAssetString), *theOffscreenRenderer);
+ m_RenderPlugins.push_back(make_pair(theAssetString, 0));
+ }
}
}
@@ -1329,10 +1345,8 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
QT3DSU32 theBinaryPathOffset = theWriteBuffer.size() - theOffsetStart;
theWriteBuffer.write(QT3DSU32(m_SourcePaths.size()));
- for (nvvector<pair<CRegisteredString, eastl::pair<bool, bool>>>::iterator iter
- = m_SourcePaths.begin(), end = m_SourcePaths.end();
- iter != end; ++iter) {
- CRegisteredString theStr(iter->first);
+ for (auto iter = m_SourcePaths.begin(), end = m_SourcePaths.end(); iter != end; ++iter) {
+ CRegisteredString theStr(theStrTable.RegisterStr(iter->first));
theStr.Remap(theStrTable.GetRemapMap());
theWriteBuffer.write(size_t(theStr.c_str()));
QT3DSU32 theSourcePathFlags = iter->second.first ? 1 : 0;
@@ -1496,37 +1510,48 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
bool firstFrame) override
{
Qt3DSRenderScene *theFirstScene = nullptr;
- for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end && theFirstScene == nullptr; ++idx)
+ for (QT3DSU32 idx = 0, end = m_Scenes.size(); idx < end; ++idx) {
if (m_Scenes[idx].second->m_RuntimePresentation == inPresentation)
theFirstScene = m_Scenes[idx].second;
+ m_Scenes[idx].second->TransferDirtyProperties();
+ }
- if (theFirstScene && theFirstScene->m_Presentation) {
- m_LastRenderedScene = theFirstScene;
- if (theFirstScene->m_Presentation->m_Scene
- && theFirstScene->m_Presentation->m_Scene->m_UseClearColor) {
- m_Context->m_Context->SetSceneColor(
- theFirstScene->m_Presentation->m_Scene->m_ClearColor);
- } else
- m_Context->m_Context->SetSceneColor(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
-
- // Setup the render rotation *before* rendering so that the magic can happen on begin
- // render.
- if (m_Context->m_RenderRotationsEnabled)
- m_Context->m_Context->SetRenderRotation(
- theFirstScene->m_Presentation->m_PresentationRotation);
- else
- m_Context->m_Context->SetRenderRotation(RenderRotationValues::NoRotation);
+ if (m_Context->m_Context->GetStereoView() != StereoViews::Right) {
+ if (theFirstScene && theFirstScene->m_Presentation) {
+ m_LastRenderedScene = theFirstScene;
+ if (theFirstScene->m_Presentation->m_Scene
+ && theFirstScene->m_Presentation->m_Scene->m_UseClearColor) {
+ m_Context->m_Context->SetSceneColor(
+ theFirstScene->m_Presentation->m_Scene->m_ClearColor);
+ } else {
+ m_Context->m_Context->SetSceneColor(QT3DSVec4(0.0f, 0.0f, 0.0f, 0.0f));
+ }
- m_Context->m_Context->SetPresentationDimensions(QSize(
- int(theFirstScene->m_Presentation->m_PresentationDimensions.x),
- int(theFirstScene->m_Presentation->m_PresentationDimensions.y)));
+ // Setup the render rotation *before* rendering so that the magic
+ // can happen on begin render.
+ if (m_Context->m_RenderRotationsEnabled) {
+ m_Context->m_Context->SetRenderRotation(
+ theFirstScene->m_Presentation->m_PresentationRotation);
+ } else {
+ m_Context->m_Context->SetRenderRotation(RenderRotationValues::NoRotation);
+ }
+
+ m_Context->m_Context->SetPresentationDimensions(QSize(
+ int(theFirstScene->m_Presentation->m_PresentationDimensions.x),
+ int(theFirstScene->m_Presentation->m_PresentationDimensions.y)));
+ }
}
m_Context->m_Context->BeginFrame(firstFrame);
- m_Context->m_RenderContext->ResetBlendState();
+ {
+ QT3DS_PERF_SCOPED_TIMER(m_Context->m_CoreContext->GetPerfTimer(),
+ "RenderContext: ResetBlendState")
+ m_Context->m_RenderContext->ResetBlendState();
+ }
+
+ // Run render tasks before prepare step
+ m_Context->m_Context->RunRenderTasks();
- // How exactly does this work, I have no idea.
- // Should we only render the first scene and not every scene, perhaps?
bool wasDirty = false;
if (theFirstScene)
wasDirty = theFirstScene->PrepareForRender();
@@ -1535,11 +1560,17 @@ struct Qt3DSRenderSceneManager : public Q3DStudio::ISceneManager,
m_Context->m_RenderContext->Clear(qt3ds::render::NVRenderClearFlags(
NVRenderClearValues::Color | NVRenderClearValues::Depth));
}
+
+ // Run render tasks after prepare step
m_Context->m_Context->RunRenderTasks();
if (theFirstScene)
theFirstScene->Render();
- m_Context->m_Context->EndFrame();
+ if (m_Context->m_Context->GetStereoMode() == StereoModes::Mono
+ || m_Context->m_Context->GetStereoView() == StereoViews::Right) {
+ // For stereo, run endframe only after right eye
+ m_Context->m_Context->EndFrame();
+ }
return wasDirty;
}
@@ -1779,11 +1810,14 @@ struct SRenderFactory : public IQt3DSRenderFactoryCore, public IQt3DSRenderFacto
};
IQt3DSRenderFactory &CreateRenderFactory(const QSurfaceFormat& format,
- bool delayedLoading) override
+ bool delayedLoading, void *signalProxy) override
{
-
- SContextTypeRenderFactory theContextFactory(format);
- m_Context->CreateRenderContext(theContextFactory, delayedLoading);
+ {
+ QT3DS_PERF_SCOPED_TIMER(GetPerfTimer(), "Context: CreateRenderContext")
+ SContextTypeRenderFactory theContextFactory(format);
+ m_Context->CreateRenderContext(theContextFactory, delayedLoading,
+ (QRuntimeViewSignalProxy *)signalProxy);
+ }
GetSceneLoader();
{
diff --git a/src/engine/Qt3DSRenderRuntimeBinding.h b/src/engine/Qt3DSRenderRuntimeBinding.h
index ad0c4e6..e12f853 100644
--- a/src/engine/Qt3DSRenderRuntimeBinding.h
+++ b/src/engine/Qt3DSRenderRuntimeBinding.h
@@ -35,6 +35,7 @@
#include "EABase/eabase.h"
#include "render/Qt3DSRenderBaseTypes.h"
#include "render/Qt3DSRenderContext.h"
+#include "Qt3DSRuntimeView.h"
#include <QSurfaceFormat>
@@ -63,7 +64,8 @@ namespace render {
{
public:
virtual IQt3DSRenderFactory &
- CreateRenderFactory(const QSurfaceFormat &format, bool delayedLoading) = 0;
+ CreateRenderFactory(const QSurfaceFormat &format, bool delayedLoading,
+ void *m_SignalProxy) = 0;
static IQt3DSRenderFactoryCore &
CreateRenderFactoryCore(const char8_t *inApplicationDirectory,
diff --git a/src/engine/Qt3DSRenderRuntimeBindingImpl.h b/src/engine/Qt3DSRenderRuntimeBindingImpl.h
index 1f0e565..191a3bc 100644
--- a/src/engine/Qt3DSRenderRuntimeBindingImpl.h
+++ b/src/engine/Qt3DSRenderRuntimeBindingImpl.h
@@ -138,13 +138,14 @@ namespace render {
}
void CreateRenderContext(qt3ds::render::IRuntimeFactoryRenderFactory &inContextFactory,
- bool delayedLoading)
+ bool delayedLoading, QRuntimeViewSignalProxy *signalProxy)
{
m_RenderContext = inContextFactory.CreateRenderContext(*m_Foundation, *m_StringTable);
+
if (m_RenderContext) {
m_Context =
m_CoreContext->CreateRenderContext(*m_RenderContext, m_PrimitivePath.c_str(),
- delayedLoading);
+ delayedLoading, signalProxy);
}
}
diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp
index 47ed8aa..82b42b1 100644
--- a/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBindingImplRenderer.cpp
@@ -157,6 +157,41 @@ struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine
return 0;
}
+ void SetStereoEyeRotation(double rotation) override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context)
+ m_BindingCore->m_Context->SetStereoEyeRotation(rotation);
+ }
+ double GetStereoEyeRotation() const override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context) {
+ return const_cast<SRenderer &>(*this).m_BindingCore->
+ m_Context->GetStereoEyeRotation();
+ }
+ QT3DS_ASSERT(false);
+ return 0;
+ }
+
+ void SetStereoProgressiveEnabled(bool enabled) override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context)
+ m_BindingCore->m_Context->SetStereoProgressiveEnabled(enabled);
+ }
+ bool GetStereoProgressiveEnabled() const override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context) {
+ return const_cast<SRenderer &>(*this).m_BindingCore->
+ m_Context->GetStereoProgressiveEnabled();
+ }
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ void SetSkipFramesInterval(int interval) override
+ {
+ if (m_BindingCore && m_BindingCore->m_Context)
+ m_BindingCore->m_Context->SetSkipFramesInterval(interval);
+ }
void SetShadeMode(Q3DStudio::TegraRenderShadeModes::Enum inShade) override
{
@@ -190,10 +225,6 @@ struct SRenderer : public Q3DStudio::ITegraApplicationRenderEngine
m_Viewport = NVRenderRect(inX, inY, inWidth, inHeight);
m_BindingCore->m_RenderContext->SetViewport(m_Viewport);
}
- void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) override
- {
- m_BindingCore->m_Context->SetViewport(inViewport);
- }
void SetMatteColor(Option<QT3DSVec4> inColor) override { m_Context->SetMatteColor(inColor); }
void setMatteEnabled(bool enabled) override { m_Context->setMatteEnabled(enabled); };
diff --git a/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
index c40dd42..7c1700d 100644
--- a/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
+++ b/src/engine/Qt3DSRenderRuntimeBindingImplTranslation.cpp
@@ -37,7 +37,7 @@
#include "Qt3DSHash.h"
#include "Qt3DSRenderPlugin.h"
#include "Qt3DSRenderPluginPropertyValue.h"
-#include "Qt3DSElementHelper.h"
+#include "Qt3DSQmlElementHelper.h"
#include "Qt3DSPresentation.h"
#include "Qt3DSApplication.h"
#include "Qt3DSRenderCustomMaterialSystem.h"
@@ -191,7 +191,7 @@ struct SRuntimePropertyParser
} else if (m_Type == Q3DStudio::ATTRIBUTETYPE_STRING) {
CRegisteredString theString =
m_RenderContext.GetStringTable().HandleToStr(m_Value.m_StringHandle);
- theElem = Q3DStudio::CElementHelper::GetElement(
+ theElem = Q3DStudio::CQmlElementHelper::GetElement(
m_Element.GetBelongedPresentation()->GetApplication(),
m_Element.GetBelongedPresentation(), theString.c_str(), &m_Element);
}
@@ -493,6 +493,7 @@ struct SRuntimePropertyParser
#define Node_LocalOpacity ATTRIBUTE_OPACITY
#define Node_RotationOrder ATTRIBUTE_ROTATIONORDER
#define Node_LeftHanded ATTRIBUTE_ORIENTATION
+#define Group_ordered ATTRIBUTE_ORDERED
#define Layer_TemporalAAEnabled ATTRIBUTE_TEMPORALAA
#define Layer_LayerEnableDepthTest ATTRIBUTE_DISABLEDEPTHTEST
#define Layer_LayerEnableDepthPrePass ATTRIBUTE_DISABLEDEPTHPREPASS
@@ -504,6 +505,10 @@ struct SRuntimePropertyParser
#define Layer_BlendType ATTRIBUTE_BLENDTYPE
#define Layer_ProgressiveAAMode ATTRIBUTE_PROGRESSIVEAA
#define Layer_MultisampleAAMode ATTRIBUTE_MULTISAMPLEAA
+#define Layer_DynamicResize ATTRIBUTE_DYNAMICRESIZE
+#define Layer_DynamicPaddingUnits ATTRIBUTE_DYNAMICPADDINGUNITS
+#define Layer_DynamicPadding ATTRIBUTE_DYNAMICPADDING
+#define Layer_DynamicCombine ATTRIBUTE_DYNAMICCOMBINE
#define Layer_HorizontalFieldValues ATTRIBUTE_HORZFIELDS
#define Layer_Left ATTRIBUTE_LEFT
#define Layer_LeftUnits ATTRIBUTE_LEFTUNITS
@@ -518,6 +523,7 @@ struct SRuntimePropertyParser
#define Layer_HeightUnits ATTRIBUTE_HEIGHTUNITS
#define Layer_Bottom ATTRIBUTE_BOTTOM
#define Layer_BottomUnits ATTRIBUTE_BOTTOMUNITS
+#define Layer_AoEnabled ATTRIBUTE_AOENABLED
#define Layer_AoStrength ATTRIBUTE_AOSTRENGTH
#define Layer_AoDistance ATTRIBUTE_AODISTANCE
#define Layer_AoSoftness ATTRIBUTE_AOSOFTNESS
@@ -635,6 +641,7 @@ struct SRuntimePropertyParser
#define Material_ReferencedMaterial ATTRIBUTE_REFERENCEDMATERIAL
#define Material_VertexColors ATTRIBUTE_VERTEXCOLORS
#define Material_TransparencyMode ATTRIBUTE_TRANSPARENCYMODE
+#define Material_CullMode ATTRIBUTE_CULLMODE
#define Image_ImagePath ATTRIBUTE_SOURCEPATH
#define Image_OffscreenRendererId ATTRIBUTE_SUBPRESENTATION
#define Image_Scale_X ATTRIBUTE_SCALEU
@@ -647,6 +654,8 @@ struct SRuntimePropertyParser
#define Image_MappingMode ATTRIBUTE_MAPPINGMODE
#define Image_HorizontalTilingMode ATTRIBUTE_TILINGMODEHORZ
#define Image_VerticalTilingMode ATTRIBUTE_TILINGMODEVERT
+#define Image_MinFilter ATTRIBUTE_MINFILTER
+#define Image_MagFilter ATTRIBUTE_MAGFILTER
#define Text_Text ATTRIBUTE_TEXTSTRING
#define Text_Font ATTRIBUTE_FONT
#define Text_FontSize ATTRIBUTE_SIZE
@@ -871,12 +880,13 @@ struct SNodeTranslator : public Qt3DSTranslator
case Q3DStudio::ATTRIBUTE_ENDTIME:
case Q3DStudio::ATTRIBUTE_IMPORTID:
case Q3DStudio::ATTRIBUTE_EYEBALL:
+ case Q3DStudio::ATTRIBUTE_CONTROLLEDPROPERTY:
// Groups have a source path property on them that we like to ignore.
case Q3DStudio::ATTRIBUTE_SOURCEPATH:
break;
default:
// Unknown attribute
- // QT3DS_ASSERT( false );
+ //QT3DS_ASSERT(false);
break;
}
}
@@ -1028,8 +1038,8 @@ struct SPathSubPathTranslator : public Qt3DSTranslator
bool updatePath = false;
CRegisteredString theAnchorType =
inParser.m_RenderContext.GetStringTable().RegisterStr("PathAnchorPoint");
- for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild;
- theChild = theChild->GetSibling()) {
+ const auto children = Element().children();
+ for (auto theChild : children) {
if (theChild->GetType() == theAnchorType) {
++numAnchors;
if (theChild->IsDirty())
@@ -1041,8 +1051,7 @@ struct SPathSubPathTranslator : public Qt3DSTranslator
theManager.ResizePathSubPathBuffer(theItem, numAnchors);
if (thePathBuffer.size()) {
QT3DSU32 anchorIndex = 0;
- for (Q3DStudio::TElement *theChild = Element().GetChild(); theChild;
- theChild = theChild->GetSibling()) {
+ for (auto theChild : children) {
if (theChild->GetType() == theAnchorType) {
if (theChild->IsDirty()) {
qt3ds::render::SPathAnchorPoint &thePoint(thePathBuffer[anchorIndex]);
@@ -1051,7 +1060,7 @@ struct SPathSubPathTranslator : public Qt3DSTranslator
++idx) {
qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo =
theChild->GetPropertyByIndex(idx);
- switch (thePropInfo.first.GetNameHash()) {
+ switch (thePropInfo.first.nameHash()) {
case Q3DStudio::ATTRIBUTE_POSITION_X:
thePoint.m_Position.x = thePropInfo.second->m_FLOAT;
break;
@@ -1351,58 +1360,90 @@ struct SDynamicObjectTranslatorContext : public STranslatorContext
}
}
}
- void ApplyChanges(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext,
- SDynamicObject &inObject, Q3DStudio::TElement &element,
+ bool ApplyChanges(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext,
+ SDynamicGraphObject &inObject, Q3DStudio::TElement &element,
IDynamicObjectSystem &inSystem)
{
+ bool ret = false;
+ IStringTable &strTable = element.GetBelongedPresentation()->GetStringTable();
if (element.GetActive()) {
NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> theProperties =
inSystem.GetProperties(inObject.m_ClassName);
BuildPropertyHashes(theProperties);
- SDynamicObject &theItem(inObject);
+ SDynamicGraphObject &theItem(inObject);
+ SDynamicObject &dynObj(*inObject.m_dynamicObject);
for (long idx = 0, end = element.GetAttributeCount(); idx < end; ++idx) {
qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo =
*element.GetPropertyByIndex(idx);
THashToOffsetMap::iterator theFind =
- m_PropertyHashes.find(thePropInfo.first.GetNameHash());
+ m_PropertyHashes.find(thePropInfo.first.nameHash());
if (theFind != m_PropertyHashes.end()) {
const SEffectPropertyEntry &theEntry(theFind->second);
const qt3ds::render::dynamic::SPropertyDefinition &theDefinition(
theProperties[theEntry.m_PropertyOffset]);
if (theEntry.m_AttributeType
- == (Q3DStudio::EAttributeType)thePropInfo.first.m_Type) {
+ == (Q3DStudio::EAttributeType)thePropInfo.first.type()) {
switch (theEntry.m_AttributeType) {
case Q3DStudio::ATTRIBUTETYPE_BOOL:
- theItem.SetPropertyValue(theDefinition,
+ dynObj.SetPropertyValue(theDefinition,
thePropInfo.second->m_INT32 ? true : false);
break;
case Q3DStudio::ATTRIBUTETYPE_FLOAT:
- theItem.SetPropertyValue(theDefinition, thePropInfo.second->m_FLOAT,
+ dynObj.SetPropertyValue(theDefinition, thePropInfo.second->m_FLOAT,
theEntry.m_DataOffset);
break;
case Q3DStudio::ATTRIBUTETYPE_INT32:
- theItem.SetPropertyValue(theDefinition,
+ dynObj.SetPropertyValue(theDefinition,
(QT3DSI32)thePropInfo.second->m_INT32);
break;
case Q3DStudio::ATTRIBUTETYPE_STRING: {
CRegisteredString theStr =
- element.GetBelongedPresentation()->GetStringTable().HandleToStr(
- thePropInfo.second->m_StringHandle);
- theItem.SetPropertyValue(theDefinition, theStr.c_str(),
- inPresentation.m_PresentationDirectory.c_str(),
- m_Workspace, inRenderContext.GetStringTable());
+ strTable.HandleToStr(thePropInfo.second->m_StringHandle);
+ SImage *img = theItem.getImage(theDefinition.m_Name);
+ if (theStr.c_str()[0] == '#') {
+ CRegisteredString imgId = strTable.RegisterStr(theStr.c_str() + 1);
+ if (!img || img->m_Id != imgId) {
+ Q3DStudio::TElement *theElem = NULL;
+ theElem = element.GetBelongedPresentation()->GetApplication()
+ .GetElementAllocator().FindElementById(theStr);
+ auto *translator = static_cast<Qt3DSTranslator *>(
+ theElem->GetAssociation());
+ img = static_cast<SImage *>(&translator->RenderObject());
+ if (img)
+ theItem.setImage(theDefinition.m_Name, img);
+ }
+ if (img) {
+ dynObj.SetPropertyValue(
+ theDefinition, theDefinition.m_Name,
+ inPresentation.m_PresentationDirectory.c_str(),
+ m_Workspace, inRenderContext.GetStringTable());
+ } else {
+ dynObj.SetPropertyValue(
+ theDefinition, {},
+ inPresentation.m_PresentationDirectory.c_str(),
+ m_Workspace, inRenderContext.GetStringTable());
+ }
+ } else {
+ if (img) {
+ img->m_ImagePath = strTable.RegisterStr(theStr.c_str());
+ img->m_Flags.SetDirty(true);
+ } else {
+ dynObj.SetPropertyValue(
+ theDefinition, {},
+ inPresentation.m_PresentationDirectory.c_str(),
+ m_Workspace, inRenderContext.GetStringTable());
+ }
+ }
} break;
default:
- // QT3DS_ASSERT( false );
break;
}
- } else {
- // QT3DS_ASSERT( false );
}
}
}
- theItem.m_Flags.SetDirty(true);
+ ret = true;
}
+ return ret;
}
};
@@ -1417,13 +1458,14 @@ struct SEffectTranslator : public Qt3DSTranslator
}
void OnElementChanged(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext,
- Q3DStudio::IPresentation &)
+ Q3DStudio::IPresentation &runtimePresentation)
{
SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element);
SEffect &theItem = *static_cast<SEffect *>(m_RenderObject);
- static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
+ bool dirty = static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
->ApplyChanges(inPresentation, inRenderContext, theItem, Element(),
inRenderContext.GetDynamicObjectSystem());
+ theItem.m_Flags.SetDirty(dirty);
theItem.SetActive(Element().GetActive(), inRenderContext.GetEffectSystem());
}
};
@@ -1439,13 +1481,14 @@ struct SCustomMaterialTranslator : public Qt3DSTranslator
}
void OnElementChanged(SPresentation &inPresentation, IQt3DSRenderContext &inRenderContext,
- Q3DStudio::IPresentation &)
+ Q3DStudio::IPresentation &runtimePresentation)
{
SRuntimePropertyParser theParser(inPresentation, inRenderContext, *m_Element);
SCustomMaterial &theItem = *static_cast<SCustomMaterial *>(m_RenderObject);
- static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
+ bool dirty = static_cast<SDynamicObjectTranslatorContext *>(m_TranslatorContext)
->ApplyChanges(inPresentation, inRenderContext, theItem, Element(),
inRenderContext.GetDynamicObjectSystem());
+ theItem.m_Flags.SetDirty(dirty);
bool active = m_Element->GetActive();
if (active != theItem.m_Flags.IsActive()) {
theItem.m_Flags.SetActive(active);
@@ -1539,11 +1582,11 @@ struct SRenderPluginTranslator : public Qt3DSTranslator
qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo =
*Element().GetPropertyByIndex(idx);
nvhash_map<int, CRegisteredString>::iterator theFind =
- theTransContext.m_AttribHashIndexMap.find(thePropInfo.first.GetNameHash());
+ theTransContext.m_AttribHashIndexMap.find(thePropInfo.first.nameHash());
if (theFind != theTransContext.m_AttribHashIndexMap.end()) {
CRegisteredString thePropName(theFind->second);
Q3DStudio::EAttributeType theType =
- (Q3DStudio::EAttributeType)thePropInfo.first.m_Type;
+ (Q3DStudio::EAttributeType)thePropInfo.first.type();
switch (theType) {
case Q3DStudio::ATTRIBUTETYPE_BOOL:
theTransContext.m_PropertyUpdates.push_back(SRenderPropertyValueUpdate(
@@ -1651,8 +1694,8 @@ struct STranslatorCreator
++idx) {
qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo =
*theTranslator.Element().GetPropertyByIndex(idx);
- theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second,
- (Q3DStudio::EAttributeType)thePropInfo.first.m_Type);
+ theParser.Setup(thePropInfo.first.nameHash(), *thePropInfo.second,
+ (Q3DStudio::EAttributeType)thePropInfo.first.type());
// right now, this is the best we can do because the attribute's dirty system
// is all jacked up.
theTranslator.OnSpecificPropertyChange(theParser);
@@ -1662,8 +1705,8 @@ struct STranslatorCreator
++idx) {
qt3ds::runtime::element::TPropertyDescAndValuePtr thePropInfo =
*theTranslator.Element().GetDynamicPropertyByIndex(idx);
- theParser.Setup(thePropInfo.first.GetNameHash(), *thePropInfo.second,
- (Q3DStudio::EAttributeType)thePropInfo.first.m_Type);
+ theParser.Setup(thePropInfo.first.nameHash(), *thePropInfo.second,
+ (Q3DStudio::EAttributeType)thePropInfo.first.type());
// right now, this is the best we can do because the attribute's dirty system
// is all jacked up.
theTranslator.OnSpecificPropertyChange(theParser);
diff --git a/src/engine/Qt3DSRuntimeView.cpp b/src/engine/Qt3DSRuntimeView.cpp
index 0a8fd54..62f7e82 100644
--- a/src/engine/Qt3DSRuntimeView.cpp
+++ b/src/engine/Qt3DSRuntimeView.cpp
@@ -52,6 +52,9 @@
#include "Qt3DSDLLManager.h"
#include "foundation/Qt3DSSimpleTypes.h"
#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSPerfTimer.h"
+#include <QtGui/qopengl.h>
+
// For perf log timestamp
#include <time.h>
#include "Qt3DSArray.h"
@@ -171,14 +174,15 @@ public:
bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override;
bool HasOfflineLoadingCompleted() override;
bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading,
- bool initInRenderThread, const QByteArray &shaderCache) override;
+ bool initInRenderThread, const QByteArray &shaderCache,
+ QString &errors) override;
void connectSignals() override;
void finishAsyncInit() override;
void Cleanup() override;
bool CanRender() override;
- void Render() override;
+ bool Render() override;
bool WasLastFrameDirty() override;
bool HandleMessage(const QEvent *inEvent) override;
@@ -227,6 +231,7 @@ public:
void deleteMeshes(const QStringList &meshNames) override;
void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) override;
uint textureId(const QString &elementPath) override;
+ uint textureId(const QString &elementPath, QSize &size, GLenum &format) override;
void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) override;
bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override;
@@ -301,16 +306,19 @@ bool CRuntimeView::HasOfflineLoadingCompleted()
}
bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading,
- bool initInRenderThread, const QByteArray &shaderCache)
+ bool initInRenderThread, const QByteArray &shaderCache,
+ QString &errors)
{
m_ApplicationCore->EndLoad();
// Next call will initialize the render portion of the scenes. This *must* have a loaded
// application to go further as it will bind scene graph data to application data.
- m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format, delayedLoading);
+ m_RuntimeFactory = m_RuntimeFactoryCore->CreateRenderFactory(format,delayedLoading,
+ signalProxy());
m_Application
= m_ApplicationCore->CreateApplication(*m_InputEngine, m_AudioPlayer,
*m_RuntimeFactory, shaderCache,
- initInRenderThread);
+ initInRenderThread,
+ errors);
if (!m_Application->createSuccessful())
return false;
@@ -324,26 +332,31 @@ bool CRuntimeView::InitializeGraphics(const QSurfaceFormat &format, bool delayed
void CRuntimeView::connectSignals()
{
- m_Presentation->signalProxy()->moveToThread(QThread::currentThread());
signalProxy()->moveToThread(QThread::currentThread());
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideEntered,
- signalProxy(), &QRuntimeViewSignalProxy::SigSlideEntered);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigSlideExited,
- signalProxy(), &QRuntimeViewSignalProxy::SigSlideExited);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigCustomSignal,
- signalProxy(), &QRuntimeViewSignalProxy::SigCustomSignal);
- QObject::connect(m_Presentation->signalProxy(),
- &QPresentationSignalProxy::SigPresentationReady,
- signalProxy(), &QRuntimeViewSignalProxy::SigPresentationReady);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigElementsCreated,
- signalProxy(), &QRuntimeViewSignalProxy::SigElementsCreated);
- QObject::connect(m_Presentation->signalProxy(), &QPresentationSignalProxy::SigMaterialsCreated,
- signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated);
- QObject::connect(m_Presentation->signalProxy(),
- &QPresentationSignalProxy::SigDataOutputValueUpdated,
- signalProxy(),
- &QRuntimeViewSignalProxy::SigDataOutputValueUpdated);
+ const auto preslist = m_Application->GetPresentationList();
+
+ // Connect signalproxies of every presentation.
+ for (const auto &it : preslist) {
+ it->signalProxy()->moveToThread((QThread::currentThread()));
+ QObject::connect(it->signalProxy(), &QPresentationSignalProxy::SigSlideEntered,
+ signalProxy(), &QRuntimeViewSignalProxy::SigSlideEntered);
+ QObject::connect(it->signalProxy(), &QPresentationSignalProxy::SigSlideExited,
+ signalProxy(), &QRuntimeViewSignalProxy::SigSlideExited);
+ QObject::connect(it->signalProxy(), &QPresentationSignalProxy::SigCustomSignal,
+ signalProxy(), &QRuntimeViewSignalProxy::SigCustomSignal);
+ QObject::connect(it->signalProxy(),
+ &QPresentationSignalProxy::SigPresentationReady,
+ signalProxy(), &QRuntimeViewSignalProxy::SigPresentationReady);
+ QObject::connect(it->signalProxy(), &QPresentationSignalProxy::SigElementsCreated,
+ signalProxy(), &QRuntimeViewSignalProxy::SigElementsCreated);
+ QObject::connect(it->signalProxy(), &QPresentationSignalProxy::SigMaterialsCreated,
+ signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated);
+ QObject::connect(it->signalProxy(),
+ &QPresentationSignalProxy::SigDataOutputValueUpdated,
+ signalProxy(),
+ &QRuntimeViewSignalProxy::SigDataOutputValueUpdated);
+ }
}
void CRuntimeView::finishAsyncInit()
@@ -357,6 +370,11 @@ void CRuntimeView::Cleanup()
{
// Q3DStudio_virtual_delete( m_Timer, CTimer );
// Q3DStudio_virtual_delete( m_PerfFileStream, CFileStream );
+ const auto preslist = m_Application->GetPresentationList();
+
+ for (const auto &it : preslist)
+ QObject::disconnect(it->signalProxy(), 0, signalProxy(), 0);
+
m_Application = nullptr;
Q3DStudio_virtual_delete(m_InputEngine, CTegraInputEngine);
if (m_RenderEngine) {
@@ -366,8 +384,6 @@ void CRuntimeView::Cleanup()
CDLLManager &theDLLManager = CDLLManager::GetDLLManager();
theDLLManager.Cleanup();
- if (m_Presentation)
- QObject::disconnect(m_Presentation->signalProxy(), 0, signalProxy(), 0);
m_InputEngine = nullptr;
m_RenderEngine = nullptr;
@@ -385,8 +401,9 @@ bool CRuntimeView::CanRender()
* returns KD_TRUE to call egl_render and swap properly, KD_FALSE if there has been no scene update
*or redraw.
*/
-void CRuntimeView::Render()
+bool CRuntimeView::Render()
{
+ bool ret = true;
if (m_Application.mPtr == nullptr) {
// InitializeGraphics has not been called
QT3DS_ASSERT(false);
@@ -394,12 +411,21 @@ void CRuntimeView::Render()
PerfLogGeneralEvent1(DATALOGGER_FRAME);
- m_Application->UpdateAndRender();
+ ret = m_Application->UpdateAndRender();
if (m_startupTime < 0 && m_startupTimer && m_startupTimer->isValid()) {
+
m_startupTime = m_startupTimer->elapsed();
m_startupTimer->invalidate();
- qCDebug(PERF_INFO, "RuntimeView: First frame at - %dms", m_startupTime);
+ double currentTime = m_Application.mPtr->GetRuntimeFactoryCore().GetPerfTimer().CurrentDuration();
+
+#ifdef QT3DS_ENABLE_PERF_LOGGING
+ // Output startup perf logging data
+ m_Application->OutputPerfLoggingData();
+#endif
+ qCDebug(PERF_INFO, "*** First frame rendered ***");
+ qCDebug(PERF_INFO, "Runtime startup time: %.0fms", currentTime);
+ qCDebug(PERF_INFO, "Application startup time: %dms", m_startupTime);
}
if (m_showOnScreenStats) {
@@ -439,6 +465,7 @@ void CRuntimeView::Render()
manager.PopState();
}
+ return ret;
}
bool CRuntimeView::WasLastFrameDirty()
@@ -610,7 +637,7 @@ void CRuntimeView::GoToTime(const char *elementPath, const float time)
Q3DStudio::CQmlEngine &theBridgeEngine
= static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
- theBridgeEngine.GotoTime(elementPath, time);
+ theBridgeEngine.GotoTime(elementPath, time, false);
}
}
@@ -756,6 +783,20 @@ uint CRuntimeView::textureId(const QString &elementPath)
return 0;
}
+uint CRuntimeView::textureId(const QString &elementPath, QSize &size, GLenum &format)
+{
+ if (m_Application) {
+ Q3DStudio::CQmlEngine &theBridgeEngine
+ = static_cast<Q3DStudio::CQmlEngine &>(m_RuntimeFactoryCore->GetScriptEngineQml());
+ return theBridgeEngine.textureId(elementPath,
+ &m_RuntimeFactory->GetQt3DSRenderContext().GetRenderer(),
+ size, format);
+ }
+ size = {};
+ format = GL_INVALID_ENUM;
+ return 0;
+}
+
void CRuntimeView::SetAttribute(const char *elementPath, const char *attributeName,
const char *value)
{
@@ -809,7 +850,7 @@ bool CRuntimeView::PeekCustomAction(char *&outElementPath, char *&outActionName)
Q3DStudio::TElement *theElement = nullptr;
actionAvailable = theBridgeEngine.PeekSignal(theElement, outActionName);
if (actionAvailable && theElement)
- outElementPath = (char *)theElement->m_Path.c_str();
+ outElementPath = (char *)theElement->path().c_str();
}
return actionAvailable;
diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h
index e3f57d1..ea0f7e3 100644
--- a/src/engine/Qt3DSRuntimeView.h
+++ b/src/engine/Qt3DSRuntimeView.h
@@ -65,6 +65,7 @@ Q_SIGNALS:
void SigElementsCreated(const QStringList &elementPaths, const QString &error);
void SigMaterialsCreated(const QStringList &materialNames, const QString &error);
void SigDataOutputValueUpdated(const QString &name, const QVariant &value);
+ void SigFrameDraw();
};
namespace qt3ds {
@@ -132,7 +133,6 @@ protected:
public:
virtual void SetViewport(INT32 inX, INT32 inY, INT32 inWidth, INT32 inHeight) = 0;
- virtual void SetApplicationViewport(const qt3ds::render::NVRenderRect &inViewport) = 0;
virtual void ensureRenderTarget() = 0;
virtual void CheckResize(bool inForce, IPresentation &inActivePresentation) = 0;
virtual QByteArray exportShaderCache(bool binaryShaders) = 0;
@@ -147,6 +147,11 @@ public:
virtual TegraRenderStereoModes::Enum GetStereoMode() const = 0;
virtual void SetStereoEyeSeparation(double separation) = 0;
virtual double GetStereoEyeSeparation() const = 0;
+ virtual void SetStereoEyeRotation(double rotation) = 0;
+ virtual double GetStereoEyeRotation() const = 0;
+ virtual void SetStereoProgressiveEnabled(bool enabled) = 0;
+ virtual bool GetStereoProgressiveEnabled() const = 0;
+ virtual void SetSkipFramesInterval(int interval) = 0;
// TODO: To be removed, not used anywhere anymore
void CycleScaleMode()
@@ -177,7 +182,8 @@ public: // loading
virtual bool BeginLoad(const QString &sourcePath, const QStringList &variantList) = 0;
virtual bool HasOfflineLoadingCompleted() = 0;
virtual bool InitializeGraphics(const QSurfaceFormat &format, bool delayedLoading,
- bool initInRenderThread, const QByteArray &shaderCache) = 0;
+ bool initInRenderThread, const QByteArray &shaderCache,
+ QString &errors) = 0;
virtual void connectSignals() = 0;
virtual void finishAsyncInit() = 0;
@@ -185,7 +191,7 @@ public: // loading
virtual bool CanRender() = 0;
- virtual void Render() = 0;
+ virtual bool Render() = 0;
virtual bool WasLastFrameDirty() = 0;
@@ -230,6 +236,7 @@ public:
virtual void deleteMeshes(const QStringList &meshNames) = 0;
virtual void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) = 0;
virtual uint textureId(const QString &elementPath) = 0;
+ virtual uint textureId(const QString &elementPath, QSize &size, GLenum &format) = 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/Qt3DSAllocator.h b/src/foundation/Qt3DSAllocator.h
index cdbbe5f..2c90593 100644
--- a/src/foundation/Qt3DSAllocator.h
+++ b/src/foundation/Qt3DSAllocator.h
@@ -36,7 +36,11 @@
#include "foundation/Qt3DSAssert.h"
#if (defined(QT3DS_WINDOWS) | defined(QT3DS_X360))
+#if _MSC_VER < 1920 // 1920+ = MSVC2019
#include <typeinfo.h>
+#else
+#include <typeinfo>
+#endif
#endif
#if (defined(QT3DS_APPLE))
#include <typeinfo>
diff --git a/src/foundation/Qt3DSPerfTimer.cpp b/src/foundation/Qt3DSPerfTimer.cpp
index 923e36e..ea8de71 100644
--- a/src/foundation/Qt3DSPerfTimer.cpp
+++ b/src/foundation/Qt3DSPerfTimer.cpp
@@ -44,6 +44,7 @@ struct STimerEntry
{
QT3DSU64 m_Total;
QT3DSU64 m_Max;
+ QT3DSU64 m_CumulativeTime;
QT3DSU32 m_UpdateCount;
CRegisteredString m_Tag;
size_t m_Order;
@@ -51,29 +52,35 @@ struct STimerEntry
STimerEntry(CRegisteredString tag, size_t order)
: m_Total(0)
, m_Max(0)
+ , m_CumulativeTime(0)
, m_UpdateCount(0)
, m_Tag(tag)
, m_Order(order)
{
}
- void Update(QT3DSU64 increment)
+ void Update(QT3DSU64 increment, QT3DSU64 cumulativeTime = 0)
{
m_Total += increment;
m_Max = increment > m_Max ? increment : m_Max;
+ m_CumulativeTime = cumulativeTime;
++m_UpdateCount;
}
- void Output(QT3DSU32 inFramesPassed)
+ void Output(QT3DSU32 idx, QT3DSU32 inFramesPassed)
{
if (m_Total) {
QT3DSU64 tensNanos = Time::sCounterFreq.toTensOfNanos(m_Total);
QT3DSU64 maxNanos = Time::sCounterFreq.toTensOfNanos(m_Max);
+ QT3DSU64 cumNanos = Time::sCounterFreq.toTensOfNanos(m_CumulativeTime);
double milliseconds = tensNanos / 100000.0;
double maxMilliseconds = maxNanos / 100000.0;
- if (inFramesPassed == 0)
- qCWarning(WARNING, PERF_INFO, "%s - %fms", m_Tag.c_str(), milliseconds);
- else {
+ double cumulativeMs = cumNanos / 100000.0;
+
+ if (inFramesPassed == 0) {
+ qCWarning(WARNING, PERF_INFO, "%d. (%d) %s - %fms = %fms", (idx+1),
+ m_UpdateCount, m_Tag.c_str(), milliseconds, cumulativeMs);
+ } else {
milliseconds /= inFramesPassed;
qCWarning(WARNING, PERF_INFO, "%s - %fms/frame-total %fms-max %u hits",
m_Tag.c_str(), milliseconds, maxMilliseconds, m_UpdateCount);
@@ -88,7 +95,7 @@ struct STimerEntry
m_UpdateCount = 0;
}
- bool operator<(const STimerEntry &other) const { return m_Order < other.m_Order; }
+ bool operator<(const STimerEntry &other) const { return m_CumulativeTime < other.m_CumulativeTime; }
};
struct SPerfTimer : public IPerfTimer
{
@@ -101,6 +108,7 @@ struct SPerfTimer : public IPerfTimer
eastl::vector<STimerEntry> m_PrintEntries;
Mutex m_Mutex;
QT3DSI32 mRefCount;
+ QT3DSU64 m_startTime;
SPerfTimer(NVFoundationBase &fnd)
: m_Foundation(fnd)
@@ -112,13 +120,20 @@ struct SPerfTimer : public IPerfTimer
QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
- void Update(const char *inId, QT3DSU64 inAmount) override
+ void StartMeasuring() override
+ {
+ Mutex::ScopedLock __locker(m_Mutex);
+ m_startTime = Time::getCurrentCounterValue();
+ }
+
+ void Update(const char *inId, QT3DSU64 inAmount, QT3DSU64 inStop) override
{
Mutex::ScopedLock __locker(m_Mutex);
+ QT3DSU64 cumulativeTime = inStop - m_startTime;
CRegisteredString theStr(m_StringTable->RegisterStr(inId));
THashMapType::iterator theFind =
m_Entries.insert(eastl::make_pair(theStr, STimerEntry(theStr, m_Entries.size()))).first;
- theFind->second.Update(inAmount);
+ theFind->second.Update(inAmount, cumulativeTime);
}
// Dump current summation of timer data.
@@ -135,7 +150,7 @@ struct SPerfTimer : public IPerfTimer
eastl::sort(m_PrintEntries.begin(), m_PrintEntries.end());
for (QT3DSU32 idx = 0, end = (QT3DSU32)m_PrintEntries.size(); idx < end; ++idx) {
- m_PrintEntries[idx].Output(inFramesPassed);
+ m_PrintEntries[idx].Output(idx, inFramesPassed);
}
}
@@ -148,6 +163,14 @@ struct SPerfTimer : public IPerfTimer
}
}
+ double CurrentDuration() override
+ {
+ QT3DSU64 duration = Time::getCurrentCounterValue() - m_startTime;
+ QT3DSU64 tensNanos = Time::sCounterFreq.toTensOfNanos(duration);
+ double durationMs = tensNanos / 100000.0;
+ return durationMs;
+ }
+
virtual void ClearPerfKeys()
{
Mutex::ScopedLock __locker(m_Mutex);
diff --git a/src/foundation/Qt3DSPerfTimer.h b/src/foundation/Qt3DSPerfTimer.h
index d539e6a..122e176 100644
--- a/src/foundation/Qt3DSPerfTimer.h
+++ b/src/foundation/Qt3DSPerfTimer.h
@@ -44,11 +44,14 @@ namespace foundation {
protected:
virtual ~IPerfTimer() {}
public:
+ virtual void StartMeasuring() = 0;
// amount is in counter frequency units
- virtual void Update(const char *inTag, QT3DSU64 inAmount) = 0;
+ virtual void Update(const char *inTag, QT3DSU64 inAmount, QT3DSU64 inStop) = 0;
// Dump current summation of timer data.
virtual void OutputTimerData(QT3DSU32 inFrameCount = 0) = 0;
virtual void ResetTimerData() = 0;
+ // Returns current duration in ms
+ virtual double CurrentDuration() = 0;
static IPerfTimer &CreatePerfTimer(NVFoundationBase &inFoundation);
};
@@ -94,7 +97,7 @@ namespace foundation {
if (m_Timer) {
QT3DSU64 theStop = Time::getCurrentCounterValue();
QT3DSU64 theAmount = theStop - m_Start;
- m_Timer->Update(m_Id, theAmount);
+ m_Timer->Update(m_Id, theAmount, theStop);
}
}
};
diff --git a/src/foundation/StringTable.h b/src/foundation/StringTable.h
index 8f7fa84..0a25a32 100644
--- a/src/foundation/StringTable.h
+++ b/src/foundation/StringTable.h
@@ -146,7 +146,7 @@ namespace foundation {
answer = *inStr - *myStr;
return answer < 0;
}
- size_t hash() const { return eastl::hash<size_t>()(reinterpret_cast<size_t>(m_String)); }
+ size_t hash() const { return qHashBits(m_String, strlen(m_String) * sizeof(char8_t)); }
operator Qt3DSBCharPtr() const { return c_str(); }
Qt3DSBCharPtr c_str() const { return m_String ? m_String : ""; }
bool IsValid() const { return m_String && *m_String; }
diff --git a/src/ogl-runtime-dylib/ogl-runtime-dylib.pro b/src/ogl-runtime-dylib/ogl-runtime-dylib.pro
index 264830f..b360205 100644
--- a/src/ogl-runtime-dylib/ogl-runtime-dylib.pro
+++ b/src/ogl-runtime-dylib/ogl-runtime-dylib.pro
@@ -80,3 +80,9 @@ PREDEPS_LIBS = qt3dsruntimestatic
include(../../utils.pri)
PRE_TARGETDEPS += $$fixLibPredeps($$LIBDIR, PREDEPS_LIBS)
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+}
diff --git a/src/ogl-runtime-static/ogl-runtime-static.pro b/src/ogl-runtime-static/ogl-runtime-static.pro
index e2480f2..85d8491 100644
--- a/src/ogl-runtime-static/ogl-runtime-static.pro
+++ b/src/ogl-runtime-static/ogl-runtime-static.pro
@@ -58,7 +58,6 @@ SOURCES += \
../runtime/Qt3DSInputEngine.cpp \
../runtime/Qt3DSLogicSystem.cpp \
../runtime/Qt3DSCommandHelper.cpp \
- ../runtime/Qt3DSElementHelper.cpp \
../runtime/Qt3DSOutputMemoryStream.cpp \
../runtime/Qt3DSParametersSystem.cpp \
../runtime/Qt3DSPresentation.cpp \
@@ -251,7 +250,6 @@ HEADERS += \
../runtime/Qt3DSInputEngine.h \
../runtime/Qt3DSLogicSystem.h \
../runtime/Qt3DSCommandHelper.h \
- ../runtime/Qt3DSElementHelper.h \
../runtime/Qt3DSOutputMemoryStream.h \
../runtime/Qt3DSParametersSystem.h \
../runtime/Qt3DSPresentation.h \
@@ -662,3 +660,9 @@ HEADERS += \
DISTFILES += \
../runtime/Qt3DSAttributeHashes.txt
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+}
diff --git a/src/qmlstreamer/q3dsqmlstream.cpp b/src/qmlstreamer/q3dsqmlstream.cpp
index c0dc6a2..caf197f 100644
--- a/src/qmlstreamer/q3dsqmlstream.cpp
+++ b/src/qmlstreamer/q3dsqmlstream.cpp
@@ -36,7 +36,7 @@
\ingroup OpenGLRuntime
\brief Allows streaming of QML as subpresentation.
- \sa Studio3D, Presentation, SubPresentation
+ \sa Studio3D, Presentation
*/
/*!
\class Q3DSQmlStream
@@ -74,10 +74,16 @@ QString Q3DSQmlStream::presentationId() const
/*!
* \qmlproperty Item QmlStream::item
* Contains the Item to be streamed as subpresentation.
+ * \note The Item width and height will be scaled up to the nearest divisible-by-four number to
+ * avoid rendering artefacts. If you wish to have pixel perfect outcome, define your QML stream
+ * items to use size that already has dimensions that are divisible by four.
*/
/*!
* \property Q3DSQmlStream::item
* Contains the QQuickItem to be streamed as subpresentation.
+ * \note The Item width and height will be scaled up to the nearest divisible-by-four number to
+ * avoid rendering artefacts. If you wish to have pixel perfect outcome, define your QML stream
+ * items to use size that already has dimensions that are divisible by four.
*/
QQuickItem *Q3DSQmlStream::item() const
{
diff --git a/src/qmlstreamer/q3dsqmlstreamrenderer.cpp b/src/qmlstreamer/q3dsqmlstreamrenderer.cpp
index f1879a6..0f7ec8e 100644
--- a/src/qmlstreamer/q3dsqmlstreamrenderer.cpp
+++ b/src/qmlstreamer/q3dsqmlstreamrenderer.cpp
@@ -392,6 +392,17 @@ void Q3DSQmlStreamRenderer::updateSizes()
{
if (m_rootItem->width() > 0 && m_rootItem->height() > 0) {
m_size = QSize(m_rootItem->width(), m_rootItem->height());
+ // Make the dimensions divisible by four; this prevents rendering artefacts
+ // In worst case scenario this increases the size by 3 pixels in each dimension
+ // TODO: Would it be possible to add transparent pixels around the original stream
+ // to meet the divisible by four -requirement, but render the original amount of pixels?
+ // That way the end result would still be pixel perfect, unlike with this implementation.
+ const int w = m_size.width();
+ const int h = m_size.height();
+ if (w % 4 != 0)
+ m_size.setWidth(w + 4 - w % 4);
+ if (h % 4 != 0)
+ m_size.setHeight(h + 4 - h % 4);
} else {
m_rootItem->setWidth(256);
m_rootItem->setHeight(256);
@@ -479,5 +490,6 @@ void Q3DSQmlStreamRenderer::render()
m_program->release();
m_vao->release();
+ m_update = false;
}
}
diff --git a/src/qmlstreamer/q3dsqmlsubpresentationsettings.cpp b/src/qmlstreamer/q3dsqmlsubpresentationsettings.cpp
index 664b9e4..739c6b5 100644
--- a/src/qmlstreamer/q3dsqmlsubpresentationsettings.cpp
+++ b/src/qmlstreamer/q3dsqmlsubpresentationsettings.cpp
@@ -58,7 +58,7 @@ Q3DSSubPresentationSettings::~Q3DSSubPresentationSettings()
}
/*!
- * \qmlproperty variant SubPresentationSettings::qmlStream
+ * \qmlproperty variant SubPresentationSettings::qmlStreams
* Contains the QML streams to be used as subpresentations.
*/
/*!
diff --git a/src/qmlstreamer/qmlstreamer.pro b/src/qmlstreamer/qmlstreamer.pro
index 5e82c7c..09c42d8 100644
--- a/src/qmlstreamer/qmlstreamer.pro
+++ b/src/qmlstreamer/qmlstreamer.pro
@@ -48,3 +48,9 @@ INCLUDEPATH += \
$$PWD/../QtExtras/qmlstreamer
macos:QMAKE_LFLAGS_SONAME = -Wl,-install_name,@rpath/
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+}
diff --git a/src/render/Qt3DSRenderBaseTypes.h b/src/render/Qt3DSRenderBaseTypes.h
index 909077d..bfe034b 100644
--- a/src/render/Qt3DSRenderBaseTypes.h
+++ b/src/render/Qt3DSRenderBaseTypes.h
@@ -351,6 +351,7 @@ struct NVRenderRenderBufferFormats
QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBA32F) \
QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(R11G11B10) \
QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGB9E5) \
+ QT3DS_RENDER_HANDLE_TEXTURE_FORMAT(RGBE8) \
QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGBA_DXT1) \
QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGB_DXT1) \
QT3DS_RENDER_HANDLE_COMPRESSED_TEXTURE_FORMAT(RGBA_DXT3) \
@@ -511,6 +512,7 @@ struct NVRenderTextureFormats
return 4;
case R32F:
return 4;
+ case RGBE8:
case RGBA8:
return 4;
case RGB8:
@@ -571,6 +573,7 @@ struct NVRenderTextureFormats
return 1;
case R32F:
return 1;
+ case RGBE8:
case RGBA8:
return 4;
case RGB8:
@@ -619,181 +622,9 @@ struct NVRenderTextureFormats
}
static void decodeToFloat(void *inPtr, QT3DSU32 byteOfs, float *outPtr,
- NVRenderTextureFormats::Enum inFmt)
- {
- outPtr[0] = 0.0f;
- outPtr[1] = 0.0f;
- outPtr[2] = 0.0f;
- outPtr[3] = 0.0f;
- QT3DSU8 *src = reinterpret_cast<QT3DSU8 *>(inPtr);
- // float divisor; // If we want to support RGBD?
- switch (inFmt) {
- case Alpha8:
- outPtr[0] = ((float)src[byteOfs]) / 255.0f;
- break;
-
- case Luminance8:
- case LuminanceAlpha8:
- case R8:
- case RG8:
- case RGB8:
- case RGBA8:
- case SRGB8:
- case SRGB8A8:
- // NOTE : RGBD Hack here for reference. Not meant for installation.
- // divisor = (NVRenderTextureFormats::getSizeofFormat(inFmt) == 4) ?
- // ((float)src[byteOfs+3]) / 255.0f : 1.0f;
- for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
- float val = ((float)src[byteOfs + i]) / 255.0f;
- outPtr[i] = (i < 3) ? powf(val, 0.4545454545f) : val;
- // Assuming RGBA8 actually means RGBD (which is stupid, I know)
- // if ( NVRenderTextureFormats::getSizeofFormat(inFmt) == 4 ) { outPtr[i] /=
- // divisor; }
- }
- // outPtr[3] = divisor;
- break;
-
- case R32F:
- outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
- break;
- case RG32F:
- outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
- outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
- break;
- case RGBA32F:
- outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
- outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
- outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
- outPtr[3] = reinterpret_cast<float *>(src + byteOfs)[3];
- break;
- case RGB32F:
- outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
- outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
- outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
- break;
-
- case R16F:
- case RG16F:
- case RGBA16F:
- for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
- // NOTE : This only works on the assumption that we don't have any denormals,
- // Infs or NaNs.
- // Every pixel in our source image should be "regular"
- QT3DSU16 h = reinterpret_cast<QT3DSU16 *>(src + byteOfs)[i];
- QT3DSU32 sign = (h & 0x8000) << 16;
- QT3DSU32 exponent = (((((h & 0x7c00) >> 10) - 15) + 127) << 23);
- QT3DSU32 mantissa = ((h & 0x3ff) << 13);
- QT3DSU32 result = sign | exponent | mantissa;
-
- if (h == 0 || h == 0x8000) {
- result = 0;
- } // Special case for zero and negative zero
- qt3ds::intrinsics::memCopy(reinterpret_cast<QT3DSU32 *>(outPtr) + i, &result, 4);
- }
- break;
-
- case R11G11B10:
- // place holder
- QT3DS_ASSERT(false);
- break;
-
- default:
- outPtr[0] = 0.0f;
- outPtr[1] = 0.0f;
- outPtr[2] = 0.0f;
- outPtr[3] = 0.0f;
- break;
- }
- }
-
+ NVRenderTextureFormats::Enum inFmt);
static void encodeToPixel(float *inPtr, void *outPtr, QT3DSU32 byteOfs,
- NVRenderTextureFormats::Enum inFmt)
- {
- QT3DSU8 *dest = reinterpret_cast<QT3DSU8 *>(outPtr);
- switch (inFmt) {
- case NVRenderTextureFormats::Alpha8:
- dest[byteOfs] = QT3DSU8(inPtr[0] * 255.0f);
- break;
-
- case Luminance8:
- case LuminanceAlpha8:
- case R8:
- case RG8:
- case RGB8:
- case RGBA8:
- case SRGB8:
- case SRGB8A8:
- for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
- inPtr[i] = (inPtr[i] > 1.0f) ? 1.0f : inPtr[i];
- if (i < 3)
- dest[byteOfs + i] = QT3DSU8(powf(inPtr[i], 2.2f) * 255.0f);
- else
- dest[byteOfs + i] = QT3DSU8(inPtr[i] * 255.0f);
- }
- break;
-
- case R32F:
- reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
- break;
- case RG32F:
- reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
- reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
- break;
- case RGBA32F:
- reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
- reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
- reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
- reinterpret_cast<float *>(dest + byteOfs)[3] = inPtr[3];
- break;
- case RGB32F:
- reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
- reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
- reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
- break;
-
- case R16F:
- case RG16F:
- case RGBA16F:
- for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
- // NOTE : This also has the limitation of not handling infs, NaNs and
- // denormals, but it should be
- // sufficient for our purposes.
- if (inPtr[i] > 65519.0f) {
- inPtr[i] = 65519.0f;
- }
- if (fabs(inPtr[i]) < 6.10352E-5f) {
- inPtr[i] = 0.0f;
- }
- QT3DSU32 f = reinterpret_cast<QT3DSU32 *>(inPtr)[i];
- QT3DSU32 sign = (f & 0x80000000) >> 16;
- QT3DSI32 exponent = (f & 0x7f800000) >> 23;
- QT3DSU32 mantissa = (f >> 13) & 0x3ff;
- exponent = exponent - 112;
- if (exponent > 31) {
- exponent = 31;
- }
- if (exponent < 0) {
- exponent = 0;
- }
- exponent = exponent << 10;
- reinterpret_cast<QT3DSU16 *>(dest + byteOfs)[i] =
- QT3DSU16(sign | exponent | mantissa);
- }
- break;
-
- case R11G11B10:
- // place holder
- QT3DS_ASSERT(false);
- break;
-
- default:
- dest[byteOfs] = 0;
- dest[byteOfs + 1] = 0;
- dest[byteOfs + 2] = 0;
- dest[byteOfs + 3] = 0;
- break;
- }
- }
+ NVRenderTextureFormats::Enum inFmt);
};
struct NVRenderTextureTargetType
diff --git a/src/render/Qt3DSRenderContext.h b/src/render/Qt3DSRenderContext.h
index e729ad1..47b860f 100644
--- a/src/render/Qt3DSRenderContext.h
+++ b/src/render/Qt3DSRenderContext.h
@@ -1063,9 +1063,9 @@ namespace render {
// copy framebuffer content between read target and render target
void BlitFramebuffer(QT3DSI32 srcX0, QT3DSI32 srcY0, QT3DSI32 srcX1, QT3DSI32 srcY1,
- QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
- NVRenderClearFlags flags,
- NVRenderTextureMagnifyingOp::Enum filter) override;
+ QT3DSI32 dstX0, QT3DSI32 dstY0, QT3DSI32 dstX1, QT3DSI32 dstY1,
+ NVRenderClearFlags flags,
+ NVRenderTextureMagnifyingOp::Enum filter) override;
void Draw(NVRenderDrawMode::Enum drawMode, QT3DSU32 count, QT3DSU32 offset) override;
void DrawIndirect(NVRenderDrawMode::Enum drawMode, QT3DSU32 offset) override;
@@ -1077,7 +1077,7 @@ namespace render {
{
return m_backend->format();
}
- virtual void resetStates()
+ virtual void resetStates() override
{
PushPropertySet();
PopPropertySet(true);
diff --git a/src/render/Qt3DSRenderShaderProgram.cpp b/src/render/Qt3DSRenderShaderProgram.cpp
index b5f2a77..2ed881a 100644
--- a/src/render/Qt3DSRenderShaderProgram.cpp
+++ b/src/render/Qt3DSRenderShaderProgram.cpp
@@ -1222,9 +1222,8 @@ namespace render {
bProgramIsValid = pProgram->link(format, &binary);
if (!bProgramIsValid && pProgram) {
- NVFoundationBase &foundation(context.GetFoundation());
qCCritical(INTERNAL_ERROR, "Failed to link binary program!!");
- WriteErrorMessage(foundation, "Program link output:", pProgram->GetErrorMessage());
+ result.errors = QStringLiteral("Binary program link failed");
// delete program
QT3DS_FREE(context.GetFoundation().getAllocator(), pProgram);
diff --git a/src/render/Qt3DSRenderTexture2D.cpp b/src/render/Qt3DSRenderTexture2D.cpp
index 577264d..16fd5c9 100644
--- a/src/render/Qt3DSRenderTexture2D.cpp
+++ b/src/render/Qt3DSRenderTexture2D.cpp
@@ -125,7 +125,7 @@ namespace render {
}
void NVRenderTexture2D::SetTextureStorage(QT3DSU32 inLevels, QT3DSU32 width, QT3DSU32 height,
- NVRenderTextureFormats::Enum formaInternal,
+ NVRenderTextureFormats::Enum formatInternal,
NVRenderTextureFormats::Enum format,
NVDataRef<QT3DSU8> dataBuffer)
{
@@ -138,9 +138,9 @@ namespace render {
m_Width = width;
m_Height = height;
- m_Format = formaInternal;
+ m_Format = formatInternal;
if (format == NVRenderTextureFormats::Unknown)
- format = formaInternal;
+ format = formatInternal;
// get max size and check value
QT3DSU32 maxWidth, maxHeight;
@@ -157,8 +157,8 @@ namespace render {
m_MaxMipLevel = inLevels - 1; // we count from 0
// only uncompressed formats are supported and no depth
- if (NVRenderTextureFormats::isUncompressedTextureFormat(formaInternal)) {
- m_Backend->CreateTextureStorage2D(m_TextureHandle, m_TexTarget, inLevels, formaInternal,
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(formatInternal)) {
+ m_Backend->CreateTextureStorage2D(m_TextureHandle, m_TexTarget, inLevels, formatInternal,
width, height);
m_Immutable = true;
diff --git a/src/render/backends/gl/Qt3DSOpenGLUtil.h b/src/render/backends/gl/Qt3DSOpenGLUtil.h
index 47f4230..bf877fb 100644
--- a/src/render/backends/gl/Qt3DSOpenGLUtil.h
+++ b/src/render/backends/gl/Qt3DSOpenGLUtil.h
@@ -969,6 +969,7 @@ namespace render {
outInternalFormat = GL_RG8;
outDataType = GL_UNSIGNED_BYTE;
return true;
+ case NVRenderTextureFormats::RGBE8:
case NVRenderTextureFormats::RGBA8:
outFormat = GL_RGBA;
outInternalFormat = GL_RGBA8;
@@ -1482,6 +1483,7 @@ namespace render {
return GL_R32UI;
case NVRenderTextureFormats::R32F:
return GL_R32F;
+ case NVRenderTextureFormats::RGBE8:
case NVRenderTextureFormats::RGBA8:
return GL_RGBA8;
case NVRenderTextureFormats::SRGB8A8:
diff --git a/src/render/backends/gl/Qt3DSRenderBackendGLBase.cpp b/src/render/backends/gl/Qt3DSRenderBackendGLBase.cpp
index ca40d93..aeaf79b 100644
--- a/src/render/backends/gl/Qt3DSRenderBackendGLBase.cpp
+++ b/src/render/backends/gl/Qt3DSRenderBackendGLBase.cpp
@@ -920,9 +920,9 @@ void NVRenderBackendGLBase::ReleaseTexture(NVRenderBackendTextureObject to)
}
void NVRenderBackendGLBase::SetTextureData2D(
- NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
- NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
- NVRenderTextureFormats::Enum format, const void *hostPtr)
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format, const void *hostPtr)
{
GLuint texID = HandleToID_cast(GLuint, size_t, to);
GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
@@ -934,11 +934,14 @@ void NVRenderBackendGLBase::SetTextureData2D(
internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
internalFormat, swizzleMode);
- GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+ GLenum glformat = 0;
+ GLenum glInternalFormat = 0;
+ GLenum gltype = GL_UNSIGNED_BYTE;
- if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) {
m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
glformat, gltype, glInternalFormat);
+ }
if (conversionRequired) {
GLenum dummy;
@@ -948,28 +951,36 @@ void NVRenderBackendGLBase::SetTextureData2D(
m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
gltype, glInternalFormat);
glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
- } else if (NVRenderTextureFormats::isDepthTextureFormat(format))
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(format)) {
m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat,
gltype, glInternalFormat);
+ }
- GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height,
- border, glformat, gltype, hostPtr));
+ if (hostPtr == nullptr && !NVRenderTextureFormats::isDepthTextureFormat(internalFormat)) {
+ void *tempPtr = calloc(width * height,
+ NVRenderTextureFormats::getSizeofFormat(internalFormat));
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width,
+ (GLsizei)height, border, glformat, gltype, tempPtr));
+ free(tempPtr);
+ } else {
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width,
+ (GLsizei)height, border, glformat, gltype, hostPtr));
+ }
GL_CALL_FUNCTION(glBindTexture(glTarget, 0));
}
// This will look very SetTextureData2D, but the target for glBindTexture will be different from
-// the target for
-// glTexImage2D.
+// the target for glTexImage2D.
void NVRenderBackendGLBase::SetTextureDataCubeFace(
- NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
- NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
- NVRenderTextureFormats::Enum format, const void *hostPtr)
+ NVRenderBackendTextureObject to, NVRenderTextureTargetType::Enum target, QT3DSU32 level,
+ NVRenderTextureFormats::Enum internalFormat, size_t width, size_t height, QT3DSI32 border,
+ NVRenderTextureFormats::Enum format, const void *hostPtr)
{
GLuint texID = HandleToID_cast(GLuint, size_t, to);
GLenum glTarget = m_Conversion.fromTextureTargetToGL(target);
GLenum glTexTarget =
- m_Conversion.fromTextureTargetToGL(NVRenderTextureTargetType::TextureCube);
+ m_Conversion.fromTextureTargetToGL(NVRenderTextureTargetType::TextureCube);
GL_CALL_FUNCTION(glActiveTexture(GL_TEXTURE0));
GL_CALL_FUNCTION(glBindTexture(glTexTarget, texID));
bool conversionRequired = format != internalFormat;
@@ -978,12 +989,14 @@ void NVRenderBackendGLBase::SetTextureDataCubeFace(
internalFormat = m_Conversion.replaceDeprecatedTextureFormat(GetRenderContextType(),
internalFormat, swizzleMode);
- GLenum glformat = 0, glInternalFormat = 0, gltype = GL_UNSIGNED_BYTE;
+ GLenum glformat = 0;
+ GLenum glInternalFormat = 0;
+ GLenum gltype = GL_UNSIGNED_BYTE;
- if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat))
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) {
m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), internalFormat,
glformat, gltype, glInternalFormat);
-
+ }
if (conversionRequired) {
GLenum dummy;
@@ -993,16 +1006,25 @@ void NVRenderBackendGLBase::SetTextureDataCubeFace(
m_Conversion.fromUncompressedTextureFormatToGL(GetRenderContextType(), format, glformat,
gltype, glInternalFormat);
glInternalFormat = m_Conversion.fromCompressedTextureFormatToGL(internalFormat);
- } else if (NVRenderTextureFormats::isDepthTextureFormat(format))
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(format)) {
m_Conversion.fromDepthTextureFormatToGL(GetRenderContextType(), format, glformat,
gltype, glInternalFormat);
+ }
// for es2 internal format must be same as format
if (GetRenderContextType() == NVRenderContextValues::GLES2)
glInternalFormat = glformat;
- GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width, (GLsizei)height,
- border, glformat, gltype, hostPtr));
+ if (hostPtr == nullptr && !NVRenderTextureFormats::isDepthTextureFormat(internalFormat)) {
+ void *tempPtr = calloc(width * height,
+ NVRenderTextureFormats::getSizeofFormat(internalFormat));
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width,
+ (GLsizei)height, border, glformat, gltype, tempPtr));
+ free(tempPtr);
+ } else {
+ GL_CALL_FUNCTION(glTexImage2D(glTarget, level, glInternalFormat, (GLsizei)width,
+ (GLsizei)height, border, glformat, gltype, hostPtr));
+ }
GL_CALL_FUNCTION(glBindTexture(glTexTarget, 0));
}
diff --git a/src/render/backends/gl/Qt3DSRenderContextGL.cpp b/src/render/backends/gl/Qt3DSRenderContextGL.cpp
index 88670ef..53af912 100644
--- a/src/render/backends/gl/Qt3DSRenderContextGL.cpp
+++ b/src/render/backends/gl/Qt3DSRenderContextGL.cpp
@@ -42,50 +42,59 @@ using namespace eastl;
namespace qt3ds {
namespace render {
- NVRenderContext &NVRenderContext::CreateGL(NVFoundationBase &foundation,
- IStringTable &inStringTable,
- const QSurfaceFormat &format)
- {
- NVRenderContext *retval = NULL;
+NVRenderContext &NVRenderContext::CreateGL(NVFoundationBase &foundation,
+ IStringTable &inStringTable,
+ const QSurfaceFormat &format)
+{
+ NVRenderContext *retval = NULL;
- QT3DS_ASSERT(format.majorVersion() >= 2);
+ QT3DS_ASSERT(format.majorVersion() >= 2);
- // create backend
- NVScopedRefCounted<IStringTable> theStringTable(inStringTable);
- NVScopedRefCounted<NVRenderBackend> theBackend;
- bool isES = format.renderableType() == QSurfaceFormat::OpenGLES;
+ // create backend
+ NVScopedRefCounted<IStringTable> theStringTable(inStringTable);
+ NVScopedRefCounted<NVRenderBackend> theBackend;
+ bool isES = format.renderableType() == QSurfaceFormat::OpenGLES;
+
+ static int envBE = qEnvironmentVariableIntValue("QT3DS_FORCE_OPENGL_BACKEND");
+ if (envBE == 1) {
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGLES2Impl)(
+ foundation, *theStringTable, format);
+ } else if (envBE == 2) {
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(
+ foundation, *theStringTable, format);
+ } else if (envBE == 3) {
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL4Impl)(
+ foundation, *theStringTable, format);
+ } else {
if (isES && (format.majorVersion() == 2
|| (format.majorVersion() == 3 && format.minorVersion() == 0))) {
- theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGLES2Impl)(foundation,
- *theStringTable,
- format);
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGLES2Impl)(
+ foundation, *theStringTable, format);
} else if (format.majorVersion() == 3 && format.minorVersion() >= 1 && !isES) {
- theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(foundation,
- *theStringTable,
- format);
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(
+ foundation, *theStringTable, format);
} else if (format.majorVersion() == 4
|| (isES && format.majorVersion() == 3 && format.minorVersion() >= 1)) {
#ifdef Q_OS_MACOS
// TODO: macOS crashes with glTextStorage2DMultisample, so fall back to OpenGL3
// for now (QT3DS-590)
- theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(foundation,
- *theStringTable,
- format);
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL3Impl)(
+ foundation, *theStringTable, format);
#else
- theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL4Impl)(foundation,
- *theStringTable,
- format);
+ theBackend = QT3DS_NEW(foundation.getAllocator(), NVRenderBackendGL4Impl)(
+ foundation, *theStringTable, format);
#endif
} else {
QT3DS_ASSERT(false);
qCCritical(INTERNAL_ERROR) << "Can't find a suitable OpenGL version for" << format;
}
+ }
+ retval = QT3DS_NEW(foundation.getAllocator(), NVRenderContextImpl)(foundation, *theBackend,
+ *theStringTable);
- retval = QT3DS_NEW(foundation.getAllocator(), NVRenderContextImpl)(foundation, *theBackend,
- *theStringTable);
+ return *retval;
+}
- return *retval;
- }
}
}
diff --git a/src/runtime/Qt3DSActivationManager.cpp b/src/runtime/Qt3DSActivationManager.cpp
index 526dd41..61261c8 100644
--- a/src/runtime/Qt3DSActivationManager.cpp
+++ b/src/runtime/Qt3DSActivationManager.cpp
@@ -46,6 +46,7 @@
#include "foundation/Qt3DSSync.h"
#include "Qt3DSRenderThreadPool.h"
#include "foundation/Qt3DSSimpleTypes.h"
+#include "Qt3DSInputEventTypes.h"
using namespace qt3ds::runtime;
using namespace qt3ds::runtime::element;
@@ -107,21 +108,6 @@ typedef nvvector<STimeEvent *> TTimeEventList;
struct STimeContext;
typedef NVDataRef<NVScopedRefCounted<STimeContext>> TTimeContextSet;
-// Tree navigation
-
-SElement *GetElementNodeFirstChild(SElement &inNode)
-{
- return inNode.m_Child;
-}
-SElement *GetElementNodeNextSibling(SElement &inNode)
-{
- return inNode.m_Sibling;
-}
-SElement *GetElementNodeParent(SElement &inNode)
-{
- return inNode.m_Parent;
-}
-
struct SScanBufferEntry
{
SElement *m_Node;
@@ -186,6 +172,7 @@ struct STimeContext
CTimePolicy m_TimePolicy;
SComponentTimePolicyOverride *m_TimePolicyOverride;
TTimeUnit m_CurrentTime;
+ TTimeUnit m_LastTime;
TElementNodePtrList m_Elements;
TTimeEventList m_TimeEventBackingStore;
TTimeEventList m_TimeEvents;
@@ -204,6 +191,7 @@ struct STimeContext
, m_Component(inComponent)
, m_TimePolicyOverride(NULL)
, m_CurrentTime(-1)
+ , m_LastTime(-1)
, m_Elements(alloc, "m_Elements")
, m_TimeEventBackingStore(alloc, "TimeEventBackingStore")
, m_TimeEvents(alloc, "TimeEvents")
@@ -216,6 +204,7 @@ struct STimeContext
, m_AllNodesDirty(true)
, m_TimeDataNeedsUpdate(true)
{
+ m_TimePolicy.Initialize();
}
QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Allocator)
@@ -343,7 +332,7 @@ struct STimeContext
}
TTimeUnit newTime = inNewTime;
- if (newTime != m_CurrentTime) {
+ if (newTime != m_CurrentTime || newTime != m_LastTime) {
SComponent &myNode = m_Component;
{
Mutex::ScopedLock __locker(m_ElementAccessMutex);
@@ -351,6 +340,7 @@ struct STimeContext
}
STimeEvent searchEvent(STimeEvent::Start, m_Allocator, m_CurrentTime);
bool forward = newTime > m_CurrentTime;
+ m_LastTime = m_CurrentTime;
m_CurrentTime = NVMax((TTimeUnit)0, newTime);
if (forward) {
@@ -405,9 +395,10 @@ struct STimeContext
{
// Note that just because a node itself does not participate in the time graph,
// this does not mean that its children do not participate in the time graph.
+ bool userOrControlled = inNode.IsUserActive() || inNode.IsControlledActive();
if (inNode.DoesParticipateInTimeGraph()) {
UpdateNodeElementInformation(inNode);
- if (inNode.IsUserActive()) {
+ if (userOrControlled) {
// Start time does not get updated if the element doesn't have ATTRIBUTE_STARTTIME.
if (inNode.m_ActivationManagerNode.m_StartTime != QT3DS_MAX_U32)
inGlobalMin = NVMax(inNode.m_ActivationManagerNode.m_StartTime, inGlobalMin);
@@ -426,7 +417,7 @@ struct STimeContext
inNode.m_ActivationManagerNode.m_StopTime = inGlobalMax;
}
// Is it worth looking at children at all
- return inNode.IsUserActive();
+ return userOrControlled;
}
void BuildTimeContext(TScanBuffer &inScanBuffer, IActivityZone &inZone)
@@ -435,23 +426,23 @@ struct STimeContext
QT3DS_ASSERT(m_TimeDataNeedsUpdate);
m_TimeDataNeedsUpdate = false;
SComponent &myNode = m_Component;
- SElement *theChild = myNode.m_Child;
- if (theChild == NULL) {
+ const auto children = myNode.children();
+ if (children.isEmpty())
return;
- }
+
inScanBuffer.clear();
- for (SElement *theChild = myNode.m_Child; theChild; theChild = theChild->m_Sibling) {
- inScanBuffer.push_back(theChild);
- }
+ for (auto child : children)
+ inScanBuffer.push_back(child);
+
for (QT3DSU32 idx = 0, end = (QT3DSU32)inScanBuffer.size(); idx < end; ++idx) {
SScanBufferEntry theEntry(inScanBuffer[idx]);
bool careAboutChildren = BuildTimeContextElementNode(
*theEntry.m_Node, theEntry.m_StartTime, theEntry.m_EndTime);
if (careAboutChildren && theEntry.m_Node->IsComponent() == false) {
- for (SElement *theChild = theEntry.m_Node->m_Child; theChild;
- theChild = theChild->m_Sibling) {
+ const auto nodeChildren = theEntry.m_Node->children();
+ for (auto child : nodeChildren) {
inScanBuffer.push_back(SScanBufferEntry(
- theChild, theEntry.m_Node->m_ActivationManagerNode.m_StartTime,
+ child, theEntry.m_Node->m_ActivationManagerNode.m_StartTime,
theEntry.m_Node->m_ActivationManagerNode.m_StopTime));
}
end = (QT3DSU32)inScanBuffer.size();
@@ -464,8 +455,8 @@ struct STimeContext
void SetElementDirty(SElement &inNode)
{
SElement *theComponentParent = &inNode.GetComponentParent();
- if (inNode.IsComponent() && inNode.m_Parent)
- theComponentParent = &inNode.m_Parent->GetComponentParent();
+ if (inNode.IsComponent() && inNode.GetParent())
+ theComponentParent = &inNode.GetParent()->GetComponentParent();
QT3DS_ASSERT(theComponentParent == &m_Component);
if (m_AllNodesDirty == false) {
@@ -481,7 +472,7 @@ struct STimeContext
// This also makes sure that if we mark all nodes dirty we continue the activate scan
// till we hit at least
// this node.
- SElement *theParent = inNode.m_Parent;
+ SElement *theParent = inNode.GetParent();
while (theParent) {
if (theParent->IsComponent()
|| theParent->m_ActivationManagerNode.m_Flags.IsChildDirty())
@@ -489,7 +480,7 @@ struct STimeContext
else {
SActivationManagerNode &theNode = theParent->m_ActivationManagerNode;
theNode.m_Flags.SetChildDirty();
- theParent = theParent->m_Parent;
+ theParent = theParent->GetParent();
}
}
}
@@ -499,7 +490,7 @@ struct STimeContext
{
if (!m_ControlledList.contains(item)) {
m_ControlledList.insert(item);
- qCInfo(TRACE_INFO) << "Element" << item.m_Name.c_str()
+ qCInfo(TRACE_INFO) << "Element" << item.name().c_str()
<< "visibility now controlled by datainput. "
"Visibility will no longer be affected by slide transitions.";
}
@@ -532,6 +523,15 @@ struct STimeContext
Mutex &inElementAccessMutex, bool &scriptBufferRequiresSort,
bool inIsActive)
{
+
+ if (inNode.Flags().HasActivityAction() && inNode.GetBelongedPresentation()) {
+ // If node has activity changing actions enabled, fire them
+ if (inIsActive)
+ inNode.GetBelongedPresentation()->FireEvent(Q3DStudio::ON_ACTIVATE, &inNode);
+ else
+ inNode.GetBelongedPresentation()->FireEvent(Q3DStudio::ON_DEACTIVATE, &inNode);
+ }
+
Mutex::ScopedLock __locker(inElementAccessMutex);
TElementAndSortKey theKey(&inNode, inNode.Depth());
if (inIsActive) {
@@ -564,23 +564,30 @@ struct STimeContext
// Block used to hide variables to avoid an error.
{
bool parentActive = true;
- SElement *theParent = inNode.m_Parent;
+ SElement *theParent = inNode.GetParent();
if (theParent != NULL)
parentActive = theParent->IsGlobalActive();
inScanBuffer.push_back(SScanBufferEntry(&inNode, parentActive));
}
-
+ bool parentDiActiveChange = false;
for (QT3DSU32 idx = 0, end = inScanBuffer.size(); idx < end; ++idx) {
SScanBufferEntry theEntry(inScanBuffer[idx]);
SElement *theScanNode = theEntry.m_Node;
QT3DS_ASSERT(theScanNode->IsIndependent() == false);
bool parentActive = theEntry.IsParentActive();
bool wasActive = theScanNode->IsGlobalActive();
-
bool isControlledByDi
= controlledList.contains(*theScanNode) && theScanNode->m_OnMaster;
-
+ if (!isControlledByDi && parentDiActiveChange && parentActive && !wasActive
+ && !theScanNode->IsTimeActive() && theScanNode->IsExplicitActive()) {
+ // Set time active for datainput activated child nodes
+ theScanNode->m_ActivationManagerNode.m_Flags.SetTimeActive(true);
+ }
+ bool diActiveChange = isControlledByDi
+ && (theScanNode->IsGlobalActive(parentActive)
+ != theScanNode->IsControlledActive());
+ parentDiActiveChange |= diActiveChange;
// Override visibility for master slide elements that have datainput eyeball controller.
bool isActive = isControlledByDi ? theScanNode->IsControlledActive()
: theScanNode->IsGlobalActive(parentActive);
@@ -591,18 +598,16 @@ struct STimeContext
if (activateChange) {
HandleActivationChange(*theScanNode, activateBuffer, deactivateBuffer, scriptBuffer,
inElementAccessMutex, scriptBufferRequiresSort, isActive);
- } else if (isControlledByDi
- && (theScanNode->IsGlobalActive(parentActive)
- != theScanNode->IsControlledActive())) {
+ } else if (diActiveChange) {
// Notify only if datainput control actually disagreed with activity value
// coming from activity manager.
- qCInfo(TRACE_INFO) << "Element" << theScanNode->m_Name.c_str()
+ qCInfo(TRACE_INFO) << "Element" << theScanNode->name().c_str()
<< "visibility persistently controlled by datainput.";
}
- if (checkChildren && theScanNode->m_Child) {
- for (SElement *theScanNodeChild = theScanNode->m_Child; theScanNodeChild;
- theScanNodeChild = theScanNodeChild->m_Sibling) {
+ if (checkChildren && !theScanNode->children().isEmpty()) {
+ const auto children = theScanNode->children();
+ for (auto theScanNodeChild : children) {
// Override visibility for master slide elements that have datainput
// eyeball controller.
isControlledByDi
@@ -627,7 +632,8 @@ struct STimeContext
if (m_AllNodesDirty == true) {
inTempDirtyList.clear();
SComponent &myNode = m_Component;
- for (SElement *theChild = myNode.m_Child; theChild; theChild = theChild->m_Sibling) {
+ const auto children = myNode.children();
+ for (auto theChild : children) {
// Independent nodes don't need to be in the dirty list.
if (theChild->IsIndependent() == false)
inTempDirtyList.push_back(theChild);
@@ -660,10 +666,9 @@ struct STimeContext
bool &scriptBufferRequiresSort, Q3DStudio::CComponentManager &inComponentManager,
IPerfTimer &inPerfTimer, IActivityZone &inZone)
{
- QT3DSU64 start = qt3ds::foundation::Time::getCurrentCounterValue();
SComponent &theContextNode = m_Component;
bool parentActive = true;
- SElement *theParent = theContextNode.m_Parent;
+ SElement *theParent = theContextNode.GetParent();
if (theParent != NULL)
parentActive = theParent->IsGlobalActive();
@@ -675,10 +680,9 @@ struct STimeContext
bool isActive = isControlledByDi ? theContextNode.IsControlledActive()
: theContextNode.IsGlobalActive(parentActive);
bool activationChange = isActive != wasActive;
- inPerfTimer.Update("ActivationManager - Update Initial Vars",
- qt3ds::foundation::Time::getCurrentCounterValue() - start);
+
if (activationChange) {
- QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager - Activation Change")
+ QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager: Activation Change")
HandleActivationChange(theContextNode, activateBuffer, deactivateBuffer, scriptBuffer,
m_ElementAccessMutex, scriptBufferRequiresSort, isActive);
m_DirtyList.clear();
@@ -687,16 +691,17 @@ struct STimeContext
Mutex::ScopedLock __locker(m_ElementAccessMutex);
// When the component is activated the first time go to the first slide
// Subsequent activations should continue from the deactivated slide
- if (theContextNode.GetCurrentSlide() == 0
- || inComponentManager.hasSlideChangeQueued(&theContextNode)) {
+
+ if (theContextNode.GetCurrentSlide() == 0 || inComponentManager.hasSlideChangeQueued(&theContextNode)) {
inComponentManager.GotoSlideIndex(&theContextNode, 1, false);
- inComponentManager.applyQueuedChanges(&theContextNode);
}
+ inComponentManager.applyQueuedChanges(&theContextNode);
} else
RemoveOverride();
}
+
if (isActive) {
- QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager - Update Local Time")
+ QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager: Update Local Time")
bool atEndOfTime = CalculateNewTime(inGlobalTime);
if (atEndOfTime) {
Mutex::ScopedLock __locker(m_ElementAccessMutex);
@@ -709,7 +714,7 @@ struct STimeContext
}
if (isActive || activationChange) {
if (m_AllNodesDirty || m_DirtyList.size()) {
- QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager - Dirty Scan")
+ QT3DS_PERF_SCOPED_TIMER(inPerfTimer, "ActivationManager: Dirty Scan")
RunDirtyScan(inScanBuffer, inTempDirtyList, activateBuffer, deactivateBuffer,
scriptBuffer, scriptBufferRequiresSort);
}
@@ -847,10 +852,10 @@ struct SActivityZone : public IActivityZone
m_Foundation.getAllocator(), static_cast<SComponent &>(theComponent),
m_ElementAccessMutex);
STimeContext &theNewContext = *inserter.first->second;
- if (theComponent.m_Parent == NULL)
+ if (theComponent.GetParent() == NULL)
m_RootContexts.push_back(theNewContext);
else {
- STimeContext &parentContext = GetItemTimeContext(*theComponent.m_Parent);
+ STimeContext &parentContext = GetItemTimeContext(*theComponent.GetParent());
parentContext.m_Children.push_back(theNewContext);
}
}
@@ -859,7 +864,7 @@ struct SActivityZone : public IActivityZone
void AddActivityItems(TActivityItem inNode) override
{
- if (inNode.m_Parent == NULL)
+ if (inNode.GetParent() == NULL)
m_RootElements.push_back(&inNode);
GetItemTimeContext(inNode);
@@ -889,8 +894,8 @@ struct SActivityZone : public IActivityZone
// else travel up the chain till you find an indpendent node.
SElement &GetItemTimeParentNode(SElement &inNode)
{
- if (inNode.m_Parent != NULL) {
- SElement &theParent = *inNode.m_Parent;
+ if (inNode.GetParent() != NULL) {
+ SElement &theParent = *inNode.GetParent();
if (theParent.IsIndependent())
return theParent;
return GetItemTimeParentNode(theParent);
@@ -948,8 +953,8 @@ struct SActivityZone : public IActivityZone
TTimeUnit GetItemLocalTime(TActivityItem item) override
{
SElement *theElem = &item.GetComponentParent();
- if (item.IsComponent() && item.m_Parent)
- theElem = &item.m_Parent->GetComponentParent();
+ if (item.IsComponent() && item.GetParent())
+ theElem = &item.GetParent()->GetComponentParent();
return GetItemTimeContext(*theElem).m_CurrentTime;
}
@@ -974,7 +979,7 @@ struct SActivityZone : public IActivityZone
void DoUpdate()
{
- QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "ActivationManager - DoUpdate")
+ QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "ActivationManager: DoUpdate")
if (m_Active) {
// We know that parent elements are added before children.
// So we know the time contexts are in an appropriate order, assuming they completely
diff --git a/src/runtime/Qt3DSAnimationSystem.cpp b/src/runtime/Qt3DSAnimationSystem.cpp
index 199b7f2..b0ad2e6 100644
--- a/src/runtime/Qt3DSAnimationSystem.cpp
+++ b/src/runtime/Qt3DSAnimationSystem.cpp
@@ -213,7 +213,7 @@ struct SAnimSystem : public IAnimationSystem
theProperty = inElement.GetPropertyByIndex(*theIndex);
if (theProperty.hasValue() == false
- || theProperty->first.m_Type != Q3DStudio::ATTRIBUTETYPE_FLOAT) {
+ || theProperty->first.type() != Q3DStudio::ATTRIBUTETYPE_FLOAT) {
QT3DS_ASSERT(false);
return 0;
}
diff --git a/src/runtime/Qt3DSAnimationSystem.h b/src/runtime/Qt3DSAnimationSystem.h
index d8ee501..843c83e 100644
--- a/src/runtime/Qt3DSAnimationSystem.h
+++ b/src/runtime/Qt3DSAnimationSystem.h
@@ -45,7 +45,7 @@ namespace runtime {
using namespace qt3ds::foundation;
namespace element {
- struct SElement;
+ class SElement;
}
class IElementAllocator;
diff --git a/src/runtime/Qt3DSApplication.cpp b/src/runtime/Qt3DSApplication.cpp
index 691d4e0..ffcfa59 100644
--- a/src/runtime/Qt3DSApplication.cpp
+++ b/src/runtime/Qt3DSApplication.cpp
@@ -324,6 +324,7 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
IBufferManager &m_bufferManager;
NVRenderContextType m_type;
bool m_preferKtx;
+ bool m_flipCompressedTextures;
QSet<QString> m_uploadSet;
QSet<QString> m_uploadWaitSet;
QSet<QString> m_deleteSet;
@@ -335,8 +336,9 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
.GetAllocator())
STextureUploadRenderTask(IImageBatchLoader &loader, IBufferManager &mgr,
- NVRenderContextType type, bool preferKtx)
+ NVRenderContextType type, bool preferKtx, bool flipCompressedTextures)
: m_batchLoader(loader), m_bufferManager(mgr), m_type(type), m_preferKtx(preferKtx),
+ m_flipCompressedTextures(flipCompressedTextures),
mRefCount(0)
{
@@ -348,59 +350,60 @@ struct STextureUploadRenderTask : public IRenderTask, public IImageLoadListener
if (!m_deleteSet.isEmpty())
m_bufferManager.unloadSet(m_deleteSet);
if (!m_uploadSet.isEmpty()) {
- nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(),
- "TempSourcePathList");
+ QVector<QString> sourcePaths;
for (auto &s : qAsConst(m_uploadSet))
- sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s));
- QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(),
- this, m_type, m_preferKtx, false);
+ sourcePaths.push_back(s);
+ QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, {}, this, m_type,
+ m_preferKtx, false);
if (id) {
m_batches[id] = m_uploadSet;
m_uploadSet.clear();
}
}
if (!m_uploadWaitSet.isEmpty()) {
- nvvector<CRegisteredString> sourcePaths(m_bufferManager.GetStringTable().GetAllocator(),
- "TempSourcePathList");
+ QVector<QString> sourcePaths;
for (auto &s : qAsConst(m_uploadWaitSet))
- sourcePaths.push_back(m_bufferManager.GetStringTable().RegisterStr(s));
- QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, CRegisteredString(),
- this, m_type, m_preferKtx, false);
+ sourcePaths.push_back(s);
+ QT3DSU32 id = m_batchLoader.LoadImageBatch(sourcePaths, {}, this, m_type,
+ m_preferKtx, false);
if (id) {
m_batchLoader.BlockUntilLoaded(id);
- m_bufferManager.loadSet(m_uploadWaitSet);
+ m_bufferManager.loadSet(m_uploadWaitSet, m_flipCompressedTextures);
m_uploadWaitSet.clear();
}
}
}
void add(const QSet<QString> &set, bool wait)
{
+ const auto resolved = IBufferManager::resolveImageSet(set, m_preferKtx);
QMutexLocker loc(&m_updateMutex);
if (wait)
- m_uploadWaitSet.unite(set);
+ m_uploadWaitSet.unite(resolved);
else
- m_uploadSet.unite(set);
- m_deleteSet.subtract(set);
+ m_uploadSet.unite(resolved);
+
+ m_deleteSet.subtract(resolved);
}
void remove(const QSet<QString> &set)
{
+ const auto resolved = IBufferManager::resolveImageSet(set, m_preferKtx);
QMutexLocker loc(&m_updateMutex);
- m_uploadSet.subtract(set);
- m_uploadWaitSet.subtract(set);
- m_deleteSet.unite(set);
+ m_uploadSet.subtract(resolved);
+ m_uploadWaitSet.subtract(resolved);
+ m_deleteSet.unite(resolved);
}
bool persistent() const override
{
return true;
}
- void OnImageLoadComplete(CRegisteredString inPath, ImageLoadResult::Enum inResult) override
+ void OnImageLoadComplete(const QString &inPath, ImageLoadResult::Enum inResult) override
{
Q_UNUSED(inPath);
Q_UNUSED(inResult);
}
void OnImageBatchComplete(QT3DSU64 inBatch) override
{
- m_bufferManager.loadSet(m_batches[inBatch]);
+ m_bufferManager.loadSet(m_batches[inBatch], m_flipCompressedTextures);
}
};
@@ -636,6 +639,7 @@ struct SApp : public IApplication
bool m_DisableState;
bool m_ProfileLogging;
bool m_LastRenderWasDirty;
+ bool m_ProgressiveLeftFrame;
QT3DSU64 m_LastFrameStartTime;
QT3DSU64 m_ThisFrameStartTime;
double m_MillisecondsSinceLastFrame;
@@ -655,7 +659,7 @@ struct SApp : public IApplication
DataOutputMap m_dataOutputDefs;
bool m_initialFrame = true;
-
+ int m_skipFrameCount = 0;
SSlideResourceCounter m_resourceCounter;
QSet<QString> m_createSet;
@@ -686,6 +690,7 @@ struct SApp : public IApplication
, m_DisableState(true)
, m_ProfileLogging(false)
, m_LastRenderWasDirty(true)
+ , m_ProgressiveLeftFrame(true)
, m_LastFrameStartTime(0)
, m_ThisFrameStartTime(0)
, m_MillisecondsSinceLastFrame(0)
@@ -931,7 +936,7 @@ struct SApp : public IApplication
void UpdatePresentations()
{
- QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(), "UpdatePresentations")
+ QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(), "UpdatePresentations: Total")
// Transfer the input frame to the kernel for pick processing
// the scene manager now handles the picking on each of its scenes
SetPickFrame(m_RuntimeFactory->GetSceneManager().AdvancePickFrame(
@@ -948,14 +953,14 @@ struct SApp : public IApplication
{
QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(),
- "UpdatePresentations - pre update")
+ "UpdatePresentations: PreUpdate")
forAllPresentations(presentations, true, [globalTime](CPresentation *p) {
p->PreUpdate(globalTime);
});
}
{
QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(),
- "UpdatePresentations - begin update")
+ "UpdatePresentations: BeginUpdate")
forAllPresentations(presentations, true, [](CPresentation *p) {
p->BeginUpdate();
});
@@ -963,14 +968,14 @@ struct SApp : public IApplication
// Allow EndUpdate and PostUpdate for inactive presentations so we can activate it
{
QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(),
- "UpdatePresentations - end update")
+ "UpdatePresentations: EndUpdate")
forAllPresentations(presentations, false, [](CPresentation *p) {
p->EndUpdate();
});
}
{
QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(),
- "UpdatePresentations - postupdate")
+ "UpdatePresentations: PostUpdate")
forAllPresentations(presentations, false, [globalTime](CPresentation *p) {
p->PostUpdate(globalTime);
});
@@ -984,7 +989,7 @@ struct SApp : public IApplication
{
{
QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(),
- "NotifyDataOutputs")
+ "Application: NotifyDataOutputs")
// Allow presentations to notify of registered data output changes
for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
@@ -1029,7 +1034,7 @@ struct SApp : public IApplication
} // End QT3DS_PERF_SCOPED_TIMER scope
}
- void UpdateScenes() { m_RuntimeFactory->GetSceneManager().Update(); }
+ bool UpdateScenes() { return m_RuntimeFactory->GetSceneManager().Update(); }
bool LazyLoadSubPresentations()
{
@@ -1086,7 +1091,7 @@ struct SApp : public IApplication
void Render()
{
- QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(), "Render")
+ QT3DS_PERF_SCOPED_TIMER(m_RuntimeFactory->GetPerfTimer(), "Application: Render")
CPresentation *pres = GetPrimaryPresentation();
if (pres) {
auto &rc = m_RuntimeFactory->GetQt3DSRenderContext();
@@ -1096,12 +1101,17 @@ struct SApp : public IApplication
.RenderPresentation(pres, m_initialFrame);
} else {
// In stereoscopic mode, render 2 times for left & right eye
- rc.SetStereoView(StereoViews::Left);
- m_LastRenderWasDirty = m_RuntimeFactory->GetSceneManager()
- .RenderPresentation(pres, m_initialFrame);
- rc.SetStereoView(StereoViews::Right);
- m_RuntimeFactory->GetSceneManager()
- .RenderPresentation(pres, m_initialFrame);
+ if (!rc.GetStereoProgressiveEnabled() || m_ProgressiveLeftFrame) {
+ rc.SetStereoView(StereoViews::Left);
+ m_LastRenderWasDirty = m_RuntimeFactory->GetSceneManager()
+ .RenderPresentation(pres, m_initialFrame);
+ }
+ if (!rc.GetStereoProgressiveEnabled() || !m_ProgressiveLeftFrame) {
+ rc.SetStereoView(StereoViews::Right);
+ m_RuntimeFactory->GetSceneManager()
+ .RenderPresentation(pres, m_initialFrame);
+ }
+ m_ProgressiveLeftFrame = !m_ProgressiveLeftFrame;
}
m_initialFrame = false;
@@ -1110,8 +1120,25 @@ struct SApp : public IApplication
void ResetDirtyCounter() { m_DirtyCountdown = 5; }
+ // Returns true when skipping the frame, false when rendering it
+ bool checkSkipFrame()
+ {
+ auto &rc = m_RuntimeFactory->GetQt3DSRenderContext();
+ int skipFrames = rc.GetSkipFramesInterval();
+ if (skipFrames == 0)
+ return false;
+
+ if (m_skipFrameCount <= 0) {
+ m_skipFrameCount = skipFrames;
+ return false;
+ }
+
+ m_skipFrameCount--;
+ return true;
+ }
+
// Update all the presentations and render them.
- void UpdateAndRender() override
+ bool UpdateAndRender() override
{
QT3DS_ASSERT(m_AppLoadContext.mPtr == NULL);
m_ThisFrameStartTime = qt3ds::foundation::Time::getCurrentCounterValue();
@@ -1145,16 +1172,23 @@ struct SApp : public IApplication
}
UpdatePresentations();
- UpdateScenes();
+ bool dirty = UpdateScenes();
// If subpresentations changed we need to check if any of them needs to be loaded.
if (LazyLoadSubPresentations()) {
// Just redo all
UpdatePresentations();
- UpdateScenes();
+ dirty |= UpdateScenes();
}
+ bool renderNextFrame = false;
+ if (m_LastRenderWasDirty || dirty || m_initialFrame)
+ renderNextFrame = true;
- Render();
+ bool skip = checkSkipFrame();
+ // If we skip rendering this frame, mark next frame to be rendered
+ renderNextFrame |= skip;
+ if (!skip)
+ Render();
m_InputEnginePtr->ClearInputFrame();
@@ -1177,14 +1211,13 @@ struct SApp : public IApplication
}
}
- m_CoreFactory->GetPerfTimer().ResetTimerData();
-
fflush(stdout);
m_LastFrameStartTime = m_ThisFrameStartTime;
if (m_LastRenderWasDirty)
ResetDirtyCounter();
else
m_DirtyCountdown = NVMax(0, m_DirtyCountdown - 1);
+ return renderNextFrame;
}
// hook this up to -layer-caching.
@@ -1208,13 +1241,15 @@ struct SApp : public IApplication
{
if (m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager()
.isReloadableResourcesEnabled()) {
+ QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(),
+ "Application: Load Slide Resources")
auto &slidesystem = presentation->GetSlideSystem();
SSlideKey key;
key.m_Component = component;
key.m_Index = index;
slidesystem.setUnloadSlide(key, false);
const QString completeName = presentation->GetName() + QLatin1Char(':')
- + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName;
+ + QString::fromUtf8(key.m_Component->name()) + QLatin1Char(':') + slideName;
qCInfo(TRACE_INFO) << "Load component slide resources: " << completeName;
m_resourceCounter.handleLoadSlide(completeName, key, slidesystem);
if (m_uploadRenderTask)
@@ -1225,6 +1260,21 @@ struct SApp : public IApplication
QVector<QString> newAssets;
getComponentSlideAssets(newAssets, presentation, component, index);
+
+ // Load subpresentations of components under non-master slides of the main scene
+ // Also load subpresentation located in master slides of sub-components
+ if (presentation->GetRoot() != component || index > 0) {
+ QVector<element::SElement *> components;
+ component->findComponents(components);
+ for (int i = 0; i < components.size(); ++i) {
+ if (components[i] != component
+ && slidesystem.isElementInSlide(*components[i], *component, index)) {
+ getComponentSlideAssets(newAssets, presentation, components[i], 0);
+ getComponentSlideAssets(newAssets, presentation, components[i], 1);
+ }
+ }
+ }
+
if (newAssets.size())
qCInfo(TRACE_INFO) << "Slide assets: " << newAssets;
for (QT3DSU32 idx = 0, end = m_OrderedAssets.size(); idx < end; ++idx) {
@@ -1286,7 +1336,7 @@ struct SApp : public IApplication
slidesystem.setUnloadSlide(key, true);
if (!slidesystem.isActiveSlide(key)) {
const QString completeName = presentation->GetName() + QLatin1Char(':')
- + QString::fromUtf8(key.m_Component->m_Name) + QLatin1Char(':') + slideName;
+ + QString::fromUtf8(key.m_Component->name()) + QLatin1Char(':') + slideName;
qCInfo(TRACE_INFO) << "Unload component slide resources: " << completeName;
m_resourceCounter.handleUnloadSlide(completeName, key, slidesystem);
@@ -1300,6 +1350,7 @@ struct SApp : public IApplication
NVConstDataRef<SElementAttributeReference> inExternalReferences,
bool initInRenderThread)
{
+ QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(), "Application: LoadUIP")
GetMetaData();
eastl::string theFile;
CFileTools::CombineBaseAndRelative(GetProjectDirectory().c_str(), inAsset.m_Src.c_str(),
@@ -1316,10 +1367,13 @@ struct SApp : public IApplication
this);
inAsset.m_Presentation = thePresentation;
thePresentation->SetFilePath(theFile.c_str());
+ int uipVersion = 0;
NVScopedReleasable<IUIPParser> theUIPParser(IUIPParser::Create(
theFile.c_str(), *m_MetaData,
m_CoreFactory->GetInputStreamFactory(),
- m_CoreFactory->GetStringTable()));
+ m_CoreFactory->GetStringTable(),
+ uipVersion));
+ thePresentation->setUIPVersion(uipVersion);
Q3DStudio::IScene *newScene = nullptr;
if (theUIPParser->Load(*thePresentation, inExternalReferences, initInRenderThread)) {
// Load the scene graph portion of the scene.
@@ -1342,10 +1396,14 @@ struct SApp : public IApplication
if (inAsset.m_Id.IsValid())
newScene->RegisterOffscreenRenderer(inAsset.m_Id);
+ // Load scene master slide resources
+ // Also load master slide resources of components located in the master slide
QVector<TElement *> components;
thePresentation->GetRoot()->findComponents(components);
- for (auto &component : qAsConst(components))
- loadComponentSlideResources(component, thePresentation, 0, "Master", true);
+ for (auto &component : qAsConst(components)) {
+ if (component->m_OnMaster || component == thePresentation->GetRoot())
+ loadComponentSlideResources(component, thePresentation, 0, "Master", true);
+ }
return true;
}
@@ -1404,14 +1462,12 @@ struct SApp : public IApplication
DataInputDef diDef;
const char8_t *name = "";
const char8_t *type = "";
- const char8_t *evaluator = "";
const char8_t *metadataStr = "";
diDef.value = QVariant::Invalid;
inReader.UnregisteredAtt("name", name);
inReader.UnregisteredAtt("type", type);
inReader.Att("min", diDef.min);
inReader.Att("max", diDef.max);
- inReader.UnregisteredAtt("evaluator", evaluator);
if (AreEqual(type, "Ranged Number"))
diDef.type = DataInOutTypeRangedNumber;
else if (AreEqual(type, "String"))
@@ -1429,11 +1485,6 @@ struct SApp : public IApplication
else if (AreEqual(type, "Variant"))
diDef.type = DataInOutTypeVariant;
- if (AreEqual(type, "Evaluator")) {
- diDef.type = DataInOutTypeEvaluator;
- diDef.evaluator = QString::fromUtf8(evaluator);
- }
-
inReader.UnregisteredAtt("metadata", metadataStr);
QString metaData = QString(metadataStr);
if (!metaData.isEmpty()) {
@@ -1575,6 +1626,7 @@ struct SApp : public IApplication
bool BeginLoad(const QString &sourcePath, const QStringList &variantList) override
{
+ m_CoreFactory->GetPerfTimer().StartMeasuring();
QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(), "Application: Begin Load")
eastl::string directory;
eastl::string filename;
@@ -1710,7 +1762,7 @@ struct SApp : public IApplication
// else assume main presentation and component:slide
}
component = presentation->GetRoot();
- if (!componentName.isNull() && componentName != component->m_Name) {
+ if (!componentName.isNull() && componentName != component->name()) {
component = CQmlElementHelper::GetElement(*this, presentation,
qPrintable(componentName), nullptr);
}
@@ -1775,7 +1827,8 @@ struct SApp : public IApplication
Q3DStudio::IAudioPlayer *inAudioPlayer,
Q3DStudio::IRuntimeFactory &inFactory,
const QByteArray &shaderCache,
- bool initInRenderThread) override
+ bool initInRenderThread,
+ QString &shaderCacheErrors) override
{
{
QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(),
@@ -1845,10 +1898,12 @@ struct SApp : public IApplication
}
- if (!shaderCache.isEmpty())
- inFactory.GetQt3DSRenderContext().GetShaderCache().importShaderCache(shaderCache);
-
- m_CoreFactory->GetPerfTimer().OutputTimerData();
+ if (!shaderCache.isEmpty()) {
+ QString errors;
+ inFactory.GetQt3DSRenderContext().GetShaderCache().importShaderCache(shaderCache, errors);
+ if (!errors.isEmpty())
+ shaderCacheErrors = errors;
+ }
m_AudioPlayer.SetPlayer(inAudioPlayer);
@@ -1857,7 +1912,9 @@ struct SApp : public IApplication
STextureUploadRenderTask(rc.GetImageBatchLoader(),
rc.GetBufferManager(),
rc.GetRenderContext().GetRenderContextType(),
- GetPrimaryPresentation()->GetScene()->preferKtx()));
+ GetPrimaryPresentation()->GetScene()->preferKtx(),
+ GetPrimaryPresentation()->GetScene()
+ ->flipCompressedTextures()));
m_uploadRenderTask->add(m_createSet, true);
m_RuntimeFactory->GetQt3DSRenderContext().GetRenderList()
.AddRenderTask(*m_uploadRenderTask);
@@ -1905,26 +1962,40 @@ struct SApp : public IApplication
Q3DStudio::IRuntimeFactory &GetRuntimeFactory() const override { return *m_RuntimeFactory.mPtr; }
Q3DStudio::IRuntimeFactoryCore &GetRuntimeFactoryCore() override { return *m_CoreFactory; }
+ Q3DStudio::CPresentation *m_primaryPresentation = nullptr;
Q3DStudio::CPresentation *GetPrimaryPresentation() override
{
- return GetPresentationById(m_PresentationId.c_str());
+ if (!m_primaryPresentation)
+ m_primaryPresentation = GetPresentationById(m_PresentationId.c_str());
+ return m_primaryPresentation;
}
- virtual Q3DStudio::CPresentation *LoadAndGetPresentationById(const char8_t *inId) override
+ virtual Q3DStudio::CPresentation *LoadAndGetPresentationById(const QString &inId) override
{
return GetPresentationById(inId, true);
}
- Q3DStudio::CPresentation *GetPresentationById(const char8_t *inId, bool load = false)
+ Q3DStudio::CPresentation *GetPresentationById(const QString &inId, bool load = false)
{
- if (!isTrivial(inId)) {
+ if (!inId.isEmpty()) {
TIdAssetMap::iterator iter
= m_AssetMap.find(m_CoreFactory->GetStringTable().RegisterStr(inId));
if (iter != m_AssetMap.end()
&& iter->second->getType() == AssetValueTypes::Presentation) {
CPresentation *ret = iter->second->getData<SPresentationAsset>().m_Presentation;
- if (!ret && load)
+ if (!ret && load) {
AssetHandlers::handlePresentation(*this, *iter->second);
+ SPresentationAsset &thePresentationAsset
+ = *iter->second->getDataPtr<SPresentationAsset>();
+ CPresentation *thePresentation = thePresentationAsset.m_Presentation;
+ if (thePresentation) {
+ QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(),
+ "Application: SetActivityZone")
+ thePresentation->SetActivityZone(
+ &m_ActivityZoneManager->CreateActivityZone(*thePresentation));
+ thePresentation->SetActive(thePresentationAsset.m_Active);
+ }
+ }
return iter->second->getData<SPresentationAsset>().m_Presentation;
}
}
@@ -2015,6 +2086,7 @@ struct SApp : public IApplication
Q3DStudio::IRuntimeMetaData &GetMetaData() override
{
+ QT3DS_PERF_SCOPED_TIMER(m_CoreFactory->GetPerfTimer(), "Application: GetMetaData")
if (!m_MetaData) {
m_MetaData = &IRuntimeMetaData::Create(m_CoreFactory->GetInputStreamFactory());
if (!m_MetaData) {
@@ -2038,6 +2110,11 @@ struct SApp : public IApplication
{
return GetElementAllocator().FindElementByHandle(inHandle);
}
+
+ void OutputPerfLoggingData() override {
+ m_CoreFactory->GetPerfTimer().OutputTimerData();
+ m_CoreFactory->GetPerfTimer().ResetTimerData();
+ }
};
struct SXMLLoader : public IAppLoadContext
@@ -2095,16 +2172,20 @@ struct SXMLLoader : public IAppLoadContext
QVector<element::SElement*> components;
mainPresentation->GetRoot()->findComponents(components);
+ // Load subpresentations of components under master slide
for (int i = 0; i < components.size(); ++i) {
- m_App.getComponentSlideAssets(initialAssets, mainPresentation, components[i], 0);
- m_App.getComponentSlideAssets(initialAssets, mainPresentation, components[i], 1);
+ if (components[i]->m_OnMaster || components[i] == mainPresentation->GetRoot()) {
+ m_App.getComponentSlideAssets(initialAssets, mainPresentation, components[i], 0);
+ m_App.getComponentSlideAssets(initialAssets, mainPresentation, components[i], 1);
+ }
}
if (!delayedLoading || (m_App.m_OrderedAssets.size() > 1 && initialAssets.size() > 0)) {
for (QT3DSU32 idx = 0, end = m_App.m_OrderedAssets.size(); idx < end; ++idx) {
QString assetId = QString::fromUtf8(m_App.m_OrderedAssets[idx].first.c_str());
- if (m_App.m_OrderedAssets[idx].first != initialStr
- && (initialAssets.contains(assetId) || !delayedLoading)) {
+ if (!m_App.GetPresentationById(qPrintable(assetId))
+ && (m_App.m_OrderedAssets[idx].first != initialStr
+ && (initialAssets.contains(assetId) || !delayedLoading))) {
SAssetValue &theAsset = *m_App.m_OrderedAssets[idx].second;
switch (theAsset.getType()) {
case AssetValueTypes::Presentation:
@@ -2180,14 +2261,16 @@ IApplication &IApplication::CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore
bool AssetHandlers::handlePresentation(SApp &app, SAssetValue &asset, bool initInRenderThread)
{
+ QT3DS_PERF_SCOPED_TIMER(app.m_CoreFactory->GetPerfTimer(), "AssetHandlers: handlePresentation")
eastl::string thePathStr;
CFileTools::CombineBaseAndRelative(app.GetProjectDirectory().c_str(),
asset.GetSource(), thePathStr);
- QDir::addSearchPath(QStringLiteral("qt3dstudio"),
- QFileInfo(QString(thePathStr.c_str()))
- .absoluteDir().absolutePath());
+ const QString absPath = QFileInfo(QString(thePathStr.c_str())).absoluteDir().absolutePath();
+ if (!QDir::searchPaths(QStringLiteral("qt3dstudio")).contains(absPath))
+ QDir::addSearchPath(QStringLiteral("qt3dstudio"), absPath);
+
SPresentationAsset &thePresentationAsset
= *asset.getDataPtr<SPresentationAsset>();
eastl::vector<SElementAttributeReference> theUIPReferences;
@@ -2199,6 +2282,10 @@ bool AssetHandlers::handlePresentation(SApp &app, SAssetValue &asset, bool initI
thePathStr.c_str());
return false;
}
+
+ app.GetRuntimeFactory().GetScriptEngineQml()
+ .initializePresentationDataInputsAndOutputs(*thePresentationAsset.m_Presentation);
+
return true;
}
@@ -2244,6 +2331,13 @@ bool IApplication::isPickingEvent(TEventCommandHash event)
|| event == ON_GROUPEDMOUSEOUT);
}
+// Checks if the event comes from timeline becoming (de)active
+bool IApplication::isActivityEvent(TEventCommandHash event)
+{
+ return (event == ON_ACTIVATE
+ || event == ON_DEACTIVATE);
+}
+
QDebug operator<<(QDebug debug, const DataInOutAttribute &value)
{
QDebugStateSaver saver(debug);
@@ -2274,9 +2368,6 @@ QDebug operator<<(QDebug debug, const DataInOutType &value)
case DataInOutType::DataInOutTypeFloat:
debug.nospace() << "DataInOutTypeFloat";
break;
- case DataInOutType::DataInOutTypeEvaluator:
- debug.nospace() << "DataInOutTypeEvaluator";
- break;
case DataInOutType::DataInOutTypeBoolean:
debug.nospace() << "DataInOutTypeBoolean";
break;
@@ -2332,11 +2423,7 @@ QDebug operator<<(QDebug debug, const DataInputDef &value)
debug.nospace() << "}, min:" << value.min;
debug.nospace() << ", min:" << value.min << ", max:" << value.max;
- debug.nospace() << ", evaluator:" << value.evaluator;
debug.nospace() << ", value:" << value.value;
- debug.nospace() << ", dependents:{";
- for (auto dep : value.dependents)
- debug << dep;
debug.nospace() << "})";
return debug;
diff --git a/src/runtime/Qt3DSApplication.h b/src/runtime/Qt3DSApplication.h
index deaafe7..fd7f027 100644
--- a/src/runtime/Qt3DSApplication.h
+++ b/src/runtime/Qt3DSApplication.h
@@ -101,7 +101,6 @@ enum DataInOutType {
DataInOutTypeRangedNumber,
DataInOutTypeString,
DataInOutTypeFloat,
- DataInOutTypeEvaluator,
DataInOutTypeBoolean,
DataInOutTypeVector4,
DataInOutTypeVector3,
@@ -122,12 +121,7 @@ struct DataInputDef
DataInOutType type = DataInOutTypeInvalid;
float min = 0.0f;
float max = 0.0f;
- QString evaluator;
- QJSValue evalFunc; // keep both evaluator string and JS function
- // to avoid having to evaluate string several times
QVariant value; // most recently set value
- // evaluator datainputs that need to re-evaluate when this datainput changes value
- QVector<QString> dependents;
QHash<QString, QString> metadata;
};
@@ -169,12 +163,12 @@ public:
virtual Q3DStudio::CPresentation *GetPrimaryPresentation() = 0;
- virtual Q3DStudio::CPresentation *LoadAndGetPresentationById(const char8_t *inId) = 0;
+ virtual Q3DStudio::CPresentation *LoadAndGetPresentationById(const QString &inId) = 0;
virtual QList<Q3DStudio::CPresentation *> GetPresentationList() = 0;
// Update all the presentations and render them. Called exactly once per frame.
- virtual void UpdateAndRender() = 0;
+ virtual bool UpdateAndRender() = 0;
virtual bool IsApplicationDirty() = 0;
@@ -251,7 +245,8 @@ public:
Q3DStudio::IAudioPlayer *inAudioPlayer,
Q3DStudio::IRuntimeFactory &inFactory,
const QByteArray &shaderCache,
- bool initInRenderThread) = 0;
+ bool initInRenderThread,
+ QString &shaderCacheErrors) = 0;
// maintains reference to runtime factory core. AppDir is where the executable is located;
// the system will expect res directory
@@ -259,6 +254,10 @@ public:
static IApplication &CreateApplicationCore(Q3DStudio::IRuntimeFactoryCore &inFactory,
const char8_t *inApplicationDirectory);
static bool isPickingEvent(Q3DStudio::TEventCommandHash event);
+ static bool isActivityEvent(Q3DStudio::TEventCommandHash event);
+
+ // This will print out and reset the startup perf logs
+ virtual void OutputPerfLoggingData() = 0;
};
bool isImagePath(const QString &path);
diff --git a/src/runtime/Qt3DSAttributeHashes.cpp b/src/runtime/Qt3DSAttributeHashes.cpp
index 9d248b7..924e10e 100644
--- a/src/runtime/Qt3DSAttributeHashes.cpp
+++ b/src/runtime/Qt3DSAttributeHashes.cpp
@@ -179,11 +179,17 @@ const char *GetAttributeString(const EAttribute inAttribute)
case ATTRIBUTE_MAPPINGMODE: return "mappingmode";
case ATTRIBUTE_SUBPRESENTATION: return "subpresentation";
case ATTRIBUTE_URI: return "uri";
+ case ATTRIBUTE_MINFILTER: return "minfilter";
+ case ATTRIBUTE_MAGFILTER: return "magfilter";
case ATTRIBUTE_TRANSPARENT: return "transparent";
case ATTRIBUTE_PROGRESSIVEAA: return "progressiveaa";
case ATTRIBUTE_MULTISAMPLEAA: return "multisampleaa";
case ATTRIBUTE_TEMPORALAA: return "temporalaa";
case ATTRIBUTE_BLENDTYPE: return "blendtype";
+ case ATTRIBUTE_DYNAMICRESIZE: return "dynamicresize";
+ case ATTRIBUTE_DYNAMICPADDINGUNITS: return "dynamicpaddingunits";
+ case ATTRIBUTE_DYNAMICPADDING: return "dynamicpadding";
+ case ATTRIBUTE_DYNAMICCOMBINE: return "dynamiccombine";
case ATTRIBUTE_HORZFIELDS: return "horzfields";
case ATTRIBUTE_LEFT: return "left";
case ATTRIBUTE_LEFTUNITS: return "leftunits";
@@ -198,6 +204,7 @@ const char *GetAttributeString(const EAttribute inAttribute)
case ATTRIBUTE_HEIGHTUNITS: return "heightunits";
case ATTRIBUTE_BOTTOM: return "bottom";
case ATTRIBUTE_BOTTOMUNITS: return "bottomunits";
+ case ATTRIBUTE_AOENABLED: return "aoenabled";
case ATTRIBUTE_AOSTRENGTH: return "aostrength";
case ATTRIBUTE_AODISTANCE: return "aodistance";
case ATTRIBUTE_AOSOFTNESS: return "aosoftness";
@@ -285,6 +292,15 @@ const char *GetAttributeString(const EAttribute inAttribute)
case ATTRIBUTE_LIFETIME: return "lifetime";
case ATTRIBUTE_CONTROLLEDPROPERTY: return "controlledproperty";
case ATTRIBUTE_OBSERVEDPROPERTY: return "observedproperty";
+ case ATTRIBUTE_ORDERED: return "ordered";
+ case ATTRIBUTE_CULLMODE: return "cullmode";
+ case ATTRIBUTE_SHY: return "shy";
+ case ATTRIBUTE_VARIANTS: return "variants";
+ case ATTRIBUTE_IGNORESPARENT: return "ignoresparent";
+ case ATTRIBUTE_BONEID: return "boneid";
+ case ATTRIBUTE_IMPORTFILE: return "importfile";
+ case ATTRIBUTE_POSEROOT: return "poseroot";
+ case ATTRIBUTE_ALPHA: return "alpha";
case ATTRIBUTE_QT_IO: return "qt.io";
default: {
static char s_UnknownHash[16];
diff --git a/src/runtime/Qt3DSAttributeHashes.h b/src/runtime/Qt3DSAttributeHashes.h
index 3f53541..5f9fdf1 100644
--- a/src/runtime/Qt3DSAttributeHashes.h
+++ b/src/runtime/Qt3DSAttributeHashes.h
@@ -170,11 +170,17 @@ enum EAttribute {
ATTRIBUTE_MAPPINGMODE = 0x002715CF, // mappingmode
ATTRIBUTE_SUBPRESENTATION = 0x03CA7426, // subpresentation
ATTRIBUTE_URI = 0x00296894, // uri
+ ATTRIBUTE_MINFILTER = 0x0165D276, // minfilter
+ ATTRIBUTE_MAGFILTER = 0x031C0635, // magfilter
ATTRIBUTE_TRANSPARENT = 0x0316BA2E, // transparent
ATTRIBUTE_PROGRESSIVEAA = 0x019F1955, // progressiveaa
ATTRIBUTE_MULTISAMPLEAA = 0x013D29FD, // multisampleaa
ATTRIBUTE_TEMPORALAA = 0x00212AFE, // temporalaa
ATTRIBUTE_BLENDTYPE = 0x0035B4F5, // blendtype
+ ATTRIBUTE_DYNAMICRESIZE = 0x030D218D, // dynamicresize
+ ATTRIBUTE_DYNAMICPADDINGUNITS = 0x01B34023, // dynamicpaddingunits
+ ATTRIBUTE_DYNAMICPADDING = 0x00A35EAE, // dynamicpadding
+ ATTRIBUTE_DYNAMICCOMBINE = 0x02CB0FC0, // dynamiccombine
ATTRIBUTE_HORZFIELDS = 0x02B8A818, // horzfields
ATTRIBUTE_LEFT = 0x0196B9B9, // left
ATTRIBUTE_LEFTUNITS = 0x02F9D2D8, // leftunits
@@ -189,6 +195,7 @@ enum EAttribute {
ATTRIBUTE_HEIGHTUNITS = 0x00C91D18, // heightunits
ATTRIBUTE_BOTTOM = 0x00F4EE75, // bottom
ATTRIBUTE_BOTTOMUNITS = 0x0174091C, // bottomunits
+ ATTRIBUTE_AOENABLED = 0x00C4166D, // aoenabled
ATTRIBUTE_AOSTRENGTH = 0x010F7ED1, // aostrength
ATTRIBUTE_AODISTANCE = 0x01DC349D, // aodistance
ATTRIBUTE_AOSOFTNESS = 0x02CCDC71, // aosoftness
@@ -276,6 +283,15 @@ enum EAttribute {
ATTRIBUTE_LIFETIME = 0x0033D297, // lifetime
ATTRIBUTE_CONTROLLEDPROPERTY = 0x022C0A1D, // controlledproperty
ATTRIBUTE_OBSERVEDPROPERTY = 0x02D1CE03, // observedproperty
+ ATTRIBUTE_ORDERED = 0x038AEAD3, // ordered
+ ATTRIBUTE_CULLMODE = 0x009C792B, // cullmode
+ ATTRIBUTE_SHY = 0x023F2FFC, // shy
+ ATTRIBUTE_VARIANTS = 0x02F3DA52, // variants
+ ATTRIBUTE_IGNORESPARENT = 0x00D43995, // ignoresparent
+ ATTRIBUTE_BONEID = 0x00871A01, // boneid
+ ATTRIBUTE_IMPORTFILE = 0x00D392FF, // importfile
+ ATTRIBUTE_POSEROOT = 0x038E5ACD, // poseroot
+ ATTRIBUTE_ALPHA = 0x011BA522, // alpha
ATTRIBUTE_QT_IO = 0x010EF2CF, // qt.io
}; // enum EAttribute
diff --git a/src/runtime/Qt3DSAttributeHashes.txt b/src/runtime/Qt3DSAttributeHashes.txt
index b8e2a7f..65c2045 100644
--- a/src/runtime/Qt3DSAttributeHashes.txt
+++ b/src/runtime/Qt3DSAttributeHashes.txt
@@ -135,12 +135,18 @@ mappingtype
mappingmode
subpresentation
uri
+minfilter
+magfilter
transparent
progressiveaa
multisampleaa
temporalaa
blendtype
+dynamicresize
+dynamicpaddingunits
+dynamicpadding
+dynamiccombine
horzfields
left
leftunits
@@ -155,6 +161,7 @@ height
heightunits
bottom
bottomunits
+aoenabled
aostrength
aodistance
aosoftness
@@ -249,3 +256,14 @@ lifetime
controlledproperty
observedproperty
+
+ordered
+cullmode
+
+shy
+variants
+ignoresparent
+boneid
+importfile
+poseroot
+alpha
diff --git a/src/runtime/Qt3DSComponentManager.cpp b/src/runtime/Qt3DSComponentManager.cpp
index 8849b5b..2665c4a 100644
--- a/src/runtime/Qt3DSComponentManager.cpp
+++ b/src/runtime/Qt3DSComponentManager.cpp
@@ -85,12 +85,16 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
return;
}
- if (theComponent->GetActive() == false) {
+ // This check prevents slide changes to inactive components from activating the component children.
+ // Slide switch can proceed only if the component is actually active.
+ if (!theComponent->GetActive() || (theComponent->AboutToDeactivate()
+ && !theComponent->IsControlledActive())) {
m_ComponentInitialSlideMap[inComponent] = inGotoData;
return;
}
SComponentGotoSlideData theGotoSlideData(inGotoData);
+ const UINT8 theCurrentSlideIndex = theComponent->GetCurrentSlide();
TComponentGotoSlideDataMap::iterator iter = m_ComponentInitialSlideMap.find(inComponent);
if (iter != m_ComponentInitialSlideMap.end()) {
@@ -98,9 +102,13 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
m_ComponentInitialSlideMap.erase(iter);
}
- const UINT8 theCurrentSlideIndex = theComponent->GetCurrentSlide();
+ QString elementPath;
+ // Primary presentation stores elementpaths with subpresentation prefix.
+ // Prepend it here so that slide change notification is directed at a correct elementpath.
+ if (&m_Presentation != m_Presentation.GetApplication().GetPrimaryPresentation())
+ elementPath = m_Presentation.GetName() + QLatin1Char(':');
- QString elementPath = QString::fromUtf8(inComponent->m_Path.c_str());
+ elementPath.append(QString::fromUtf8(inComponent->path().c_str()));
if (inSlideExit) {
SEventCommand theEvent = { inComponent, EVENT_ONSLIDEEXIT };
@@ -170,7 +178,7 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
theComponent->SetPlayThrough(true);
}
- // Reset time for component to 0
+ // Reset time for component to 0 (unless we have gototime in queue).
if (theGotoSlideData.m_Paused.hasValue())
thePolicy.SetPaused(*theGotoSlideData.m_Paused);
@@ -178,8 +186,16 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
thePolicy.SetRate(theGotoSlideData.m_Rate);
thePolicy.SetReverse(theGotoSlideData.m_Reverse);
- if (theGotoSlideData.m_StartTime.hasValue())
- thePolicy.SetTime(*theGotoSlideData.m_StartTime);
+ if (!HasComponentGotoTimeCommand(theComponent)) {
+ if (theGotoSlideData.m_StartTime.hasValue())
+ thePolicy.SetTime(*theGotoSlideData.m_StartTime);
+ } else {
+ auto &timeValue = m_ComponentGotoTimeMap[theComponent];
+ TTimeUnit time = timeValue.first;
+ if (timeValue.second)
+ time = TTimeUnit(qreal(thePolicy.GetLoopingDuration()) * (qreal(time) / 1000.0));
+ thePolicy.SetTime(time);
+ }
inComponent->SetDirty();
m_Presentation.FireEvent(EVENT_ONSLIDEENTER, inComponent);
@@ -187,9 +203,10 @@ void CComponentManager::GotoSlideIndex(TElement *inComponent,
if (theZone)
theZone->OnSlideChange(*inComponent);
- m_Presentation.GetApplication().ComponentSlideEntered(&m_Presentation, inComponent,
- elementPath, theGotoSlideData.m_Slide,
- GetCurrentSlideName(inComponent));
+ ReleaseComponentGotoTimeCommand(inComponent);
+ m_Presentation.GetApplication().ComponentSlideEntered(&m_Presentation, inComponent,
+ elementPath, theGotoSlideData.m_Slide,
+ GetCurrentSlideName(inComponent));
// Signal current slide change
m_Presentation.signalProxy()->SigSlideEntered(elementPath, GetCurrentSlide(inComponent),
GetCurrentSlideName(inComponent));
@@ -329,10 +346,10 @@ void CComponentManager::applyQueuedChanges(TElement *component)
}
void CComponentManager::queueChange(TElement *component, TElement *target, const char *attName,
- const char *value)
+ const char *value, TAttributeHash attrHash)
{
CQmlElementHelper::TypedAttributeAndValue attributeAndValue
- = CQmlElementHelper::getTypedAttributeAndValue(target, attName, value);
+ = CQmlElementHelper::getTypedAttributeAndValue(target, attName, value, attrHash);
if (attributeAndValue.attribute.m_Hash != 0) {
auto &targetQueue = m_queuedChanges[component];
auto &attQueue = targetQueue[target];
@@ -345,6 +362,11 @@ bool CComponentManager::hasSlideChangeQueued(TElement *component)
return m_ComponentInitialSlideMap.find(component) != m_ComponentInitialSlideMap.end();
}
+bool CComponentManager::clearSlideChangeQueued(TElement *component)
+{
+ return m_ComponentInitialSlideMap.erase(component);
+}
+
//==============================================================================
/**
* Performs a switch to the previous slide.
@@ -362,16 +384,29 @@ void CComponentManager::GoToBackSlide(TElement *inComponent)
* @param inComponent reference to the TComponent
* @param inTime supplied time
*/
-void CComponentManager::GoToTime(TElement *inComponent, const TTimeUnit inTime)
+void CComponentManager::GoToTime(TElement *inComponent, const TTimeUnit inTime, bool relative)
{
if (inComponent == NULL)
return;
- if (!inComponent->GetActive() && !inComponent->AboutToActivate()) {
+
+ if (!inComponent->GetActive() && !inComponent->AboutToActivate()
+ && !inComponent->IsAnyParentAboutToActivate()) {
qCCritical(qt3ds::INVALID_OPERATION)
<< "Runtime: Attempt to goto time on inactive component!";
return;
}
- m_Presentation.GetActivityZone()->GoToTime(*inComponent, inTime);
+ SetupComponentGotoTimeCommand(inComponent, inTime, relative);
+ TTimeUnit time = inTime;
+ if (relative) {
+ TTimeUnit endTime = 0;
+ TComponent *component = static_cast<TComponent *>(inComponent);
+ endTime = component->GetTimePolicy().GetLoopingDuration();
+ if (endTime == CTimePolicy::FOREVER)
+ endTime = component->m_ActivationManagerNode.m_StopTime;
+ // Normalize the value to dataInput range
+ time = TTimeUnit(qreal(endTime) * (qreal(inTime) / 1000.0));
+ }
+ m_Presentation.GetActivityZone()->GoToTime(*inComponent, time);
inComponent->SetDirty();
}
@@ -518,4 +553,26 @@ void CComponentManager::ReleaseComponentGotoSlideCommand(TElement *inElement)
m_ComponentGotoSlideMap.erase(iter);
}
+bool CComponentManager::HasComponentGotoTimeCommand(TElement *inElement)
+{
+ return m_ComponentGotoTimeMap.find(inElement) != m_ComponentGotoTimeMap.end();
+}
+
+void CComponentManager::ReleaseComponentGotoTimeCommand(TElement *inElement)
+{
+ TComponentGotoTimeMap::iterator iter = m_ComponentGotoTimeMap.find(inElement);
+ if (iter != m_ComponentGotoTimeMap.end())
+ m_ComponentGotoTimeMap.erase(iter);
+}
+
+void CComponentManager::ClearGotoTimeQueue()
+{
+ m_ComponentGotoTimeMap.clear();
+}
+
+void CComponentManager::SetupComponentGotoTimeCommand(TElement *inElement, TTimeUnit time, bool relative)
+{
+ m_ComponentGotoTimeMap[inElement] = std::pair<TTimeUnit, bool>(time, relative);
+}
+
} // namespace Q3DStudio
diff --git a/src/runtime/Qt3DSComponentManager.h b/src/runtime/Qt3DSComponentManager.h
index 6ede073..4f7677f 100644
--- a/src/runtime/Qt3DSComponentManager.h
+++ b/src/runtime/Qt3DSComponentManager.h
@@ -67,6 +67,7 @@ struct SComponentTimePolicyOverride
};
typedef eastl::hash_map<TElement *, SComponentGotoSlideData> TComponentGotoSlideDataMap;
+typedef eastl::hash_map<TElement *, std::pair<TTimeUnit, bool>> TComponentGotoTimeMap;
typedef eastl::hash_map<TElement *, Q3DStudio::INT32> TComponentIntMap;
//==============================================================================
@@ -93,8 +94,9 @@ public: // Slide
void PlaythroughToSlide(TElement *inComponent);
void applyQueuedChanges(TElement *component) override;
void queueChange(TElement *component, TElement *target, const char *attName,
- const char *value) override;
+ const char *value, Q3DStudio::TAttributeHash attrHash) override;
bool hasSlideChangeQueued(TElement *component) override;
+ bool clearSlideChangeQueued(TElement *component) override;
UINT8 GetSlideCount(TElement *inComponent) override;
UINT8 GetCurrentSlide(TElement *inComponent) override;
@@ -116,8 +118,13 @@ public: // Slide
SComponentGotoSlideData GetComponentGotoSlideCommand(TElement *inElement) override;
void ReleaseComponentGotoSlideCommand(TElement *inElement) override;
+ bool HasComponentGotoTimeCommand(TElement *inElement) override;
+ void SetupComponentGotoTimeCommand(TElement *inElement, Q3DStudio::TTimeUnit time, bool relative) override;
+ void ReleaseComponentGotoTimeCommand(TElement *inElement) override;
+ void ClearGotoTimeQueue() override;
+
public: // Time
- void GoToTime(TElement *inComponent, const TTimeUnit inTime) override;
+ void GoToTime(TElement *inComponent, const TTimeUnit inTime, bool relative) override;
void SetPause(TElement *inComponent, const BOOL inPause) override;
void SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration,
const UINT32 inRepetitions, const BOOL inPingPong, const BOOL inPlayThrough) override;
@@ -136,6 +143,8 @@ private:
TComponentGotoSlideDataMap m_ComponentInitialSlideMap;
TComponentGotoSlideDataMap m_ComponentGotoSlideMap;
+ TComponentGotoTimeMap m_ComponentGotoTimeMap;
+
TComponentIntMap m_PlaythroughOverrideMap;
QHash<TElement *, QHash<TElement *, QHash<TAttributeHash, UVariant>>> m_queuedChanges;
diff --git a/src/runtime/Qt3DSElementHelper.cpp b/src/runtime/Qt3DSElementHelper.cpp
deleted file mode 100644
index 4bab37b..0000000
--- a/src/runtime/Qt3DSElementHelper.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 1993-2009 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "RuntimePrefix.h"
-
-#include "Qt3DSElementHelper.h"
-#include "Qt3DSPresentation.h"
-#include "Qt3DSApplication.h"
-#include "Qt3DSCommandEventTypes.h"
-
-using namespace qt3ds;
-
-namespace Q3DStudio {
-
-const char PRESENTATION_DELIMITER = ':';
-const char NODE_DELIMITER = '.';
-const TStringHash RESERVED_THIS = CHash::HashString("this");
-const TStringHash RESERVED_PARENT = CHash::HashString("parent");
-const TStringHash RESERVED_SCENE = CHash::HashString("Scene");
-
-CElementHelper::CElementHelper()
-{
-}
-
-CElementHelper::~CElementHelper()
-{
-}
-
-TElement *CElementHelper::GetElement(qt3ds::runtime::IApplication &inApplication,
- IPresentation *inDefaultPresentation, const char *inPath,
- TElement *inStartElement)
-{
- if (!inPath || *inPath == 0)
- return nullptr;
- const char *thePath(inPath);
- const char *theSubPath = nullptr;
- IPresentation *thePresentation = nullptr;
- size_t thePathLength = ::strlen(thePath) + 1;
- char *theToken = Q3DStudio_allocate_desc(CHAR, thePathLength, "Token:TempPath");
- // Try to get the specified presentation
- theSubPath = ::strchr(thePath, PRESENTATION_DELIMITER);
- TElement *theElement = inStartElement;
- if (theSubPath) {
- UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
-
- ::strncpy(theToken, thePath, theSubPathLength);
- theToken[theSubPathLength] = '\0';
-
- thePath = theSubPath + 1;
-
- const CHAR *thePresentationName = theToken;
-
- thePresentation = inApplication.LoadAndGetPresentationById(thePresentationName);
- }
-
- if (!thePresentation)
- thePresentation = inDefaultPresentation;
-
- // Return nil if the inStartElement is not in the specified presentation
- if (theElement
- && (!theSubPath && theElement->GetBelongedPresentation() != thePresentation)) {
- thePresentation = theElement->GetBelongedPresentation();
- }
-
- if (!thePresentation)
- return nullptr;
-
- TStringHash theName;
- INT32 theParseCounter = 0;
-
- while (thePath && thePath[0] != '\0') {
- ++theParseCounter;
-
- // Do some strtok() work here
- theSubPath = ::strchr(thePath, NODE_DELIMITER);
- if (theSubPath) {
- UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
- Q3DStudio_ASSERT(theSubPathLength < thePathLength);
-
- ::strncpy(theToken, thePath, theSubPathLength);
- theToken[theSubPathLength] = '\0';
-
- thePath = theSubPath + 1;
- } else {
- ::strcpy(theToken, thePath);
- thePath = nullptr;
- }
-
- // Hash the token and do some element searching
- theName = CHash::HashString(theToken);
-
- if (theName == RESERVED_PARENT) {
- if (theElement)
- theElement = theElement->GetParent();
- } else if (theName == RESERVED_THIS) {
- ;
- } else {
- if (theName == RESERVED_SCENE && theParseCounter == 1) {
- // theElement is nullptr, so using absolute path
- theElement = thePresentation->GetRoot();
- } else if (theElement) {
- // Using relative path
- theElement = theElement->FindChild(theName);
- }
- }
-
- if (!theElement)
- thePath = nullptr;
- } // while
-
- Q3DStudio_free(theToken, CHAR, thePathLength);
- return theElement;
-}
-} // namespace Q3DStudio
diff --git a/src/runtime/Qt3DSElementHelper.h b/src/runtime/Qt3DSElementHelper.h
deleted file mode 100644
index df2afdd..0000000
--- a/src/runtime/Qt3DSElementHelper.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 1993-2009 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#pragma once
-
-namespace qt3ds {
-namespace runtime {
- class IApplication;
-}
-}
-
-namespace Q3DStudio {
-
-class IPresentation;
-
-class CElementHelper
-{
-private:
- CElementHelper();
- CElementHelper(const CElementHelper &);
- CElementHelper &operator=(const CElementHelper &);
- virtual ~CElementHelper();
-
-public:
- static TElement *GetElement(qt3ds::runtime::IApplication &inApplication,
- IPresentation *inDefaultPresentation, const char *inPath,
- TElement *inStartElement = nullptr);
-};
-
-} // namespace Q3DStudio
diff --git a/src/runtime/Qt3DSElementSystem.cpp b/src/runtime/Qt3DSElementSystem.cpp
index 27bca95..3234e09 100644
--- a/src/runtime/Qt3DSElementSystem.cpp
+++ b/src/runtime/Qt3DSElementSystem.cpp
@@ -44,6 +44,8 @@
#include "foundation/IOStreams.h"
#include "foundation/Qt3DSIndexableLinkedList.h"
#include "Qt3DSAnimationSystem.h"
+#include "Qt3DSRenderRuntimeBindingImpl.h"
+#include "Qt3DSRenderGraphObject.h"
using namespace qt3ds::runtime::element;
using namespace qt3ds;
@@ -65,7 +67,7 @@ struct SPropertyDescSorter
{
bool operator()(const TPropertyDescAndValue &lhs, const TPropertyDescAndValue &rhs) const
{
- return strcmp(lhs.first.m_Name.c_str(), rhs.first.m_Name.c_str()) < 0;
+ return strcmp(lhs.first.name().c_str(), rhs.first.name().c_str()) < 0;
}
};
QT3DSU32 GetNumValueAllocations(const STypeDesc &inTypeDesc)
@@ -165,7 +167,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
GetIgnoredProperties();
const bool isImage = inType == m_StringTable.RegisterStr("Image");
for (QT3DSU32 idx = 0, end = inPropertyDescriptions.size(); idx < end; ++idx) {
- QT3DSU32 nameHash = inPropertyDescriptions[idx].first.GetNameHash();
+ QT3DSU32 nameHash = inPropertyDescriptions[idx].first.nameHash();
// Make image instances explicitly not participate in the timegraph. This way their
// default start/end time does not have impact into lifetimes of their parents.
// This fixes QT3DS-3669 where image default end time overrode parent endtime when
@@ -175,7 +177,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
participatesInTimeGraph = true;
}
if (eastl::find(m_IgnoredProperties.begin(), m_IgnoredProperties.end(),
- inPropertyDescriptions[idx].first.m_Name)
+ inPropertyDescriptions[idx].first.name())
== m_IgnoredProperties.end()) {
m_TempPropertyDescsAndValues.push_back(inPropertyDescriptions[idx]);
}
@@ -210,19 +212,11 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
SElement *retval = inIsComponent ? m_Components.construct(theTypeDesc, __FILE__, __LINE__)
: m_Elements.construct(theTypeDesc, __FILE__, __LINE__);
retval->m_BelongedPresentation = inPresentation;
- retval->m_Name = inName;
+ retval->setName(inName);
// children
- if (inParent) {
- retval->m_Parent = inParent;
- if (inParent->m_Child == NULL) {
- inParent->m_Child = retval;
- } else {
- SElement *lastChild = inParent->m_Child;
- while (lastChild->m_Sibling)
- lastChild = lastChild->m_Sibling;
- lastChild->m_Sibling = retval;
- }
- }
+ if (inParent)
+ retval->setParent(inParent);
+
while (FindElementByHandle(m_NextElementHandle)) {
++m_NextElementHandle;
if (!m_NextElementHandle)
@@ -264,25 +258,13 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
void ReleaseElement(SElement &inElement, bool inRecurse) override
{
if (inRecurse) {
- while (inElement.m_Child)
- ReleaseElement(*inElement.m_Child, true);
+ const auto children = inElement.children();
+ for (auto child : children)
+ ReleaseElement(*child, true);
}
// Trim out the element.
- if (inElement.m_Parent) {
- SElement *theParent = inElement.m_Parent;
- if (theParent->m_Child == &inElement)
- theParent->m_Child = inElement.m_Sibling;
- else {
- SElement *thePreviousChild = NULL;
- // Empty loop to find the previous child
- for (thePreviousChild = theParent->m_Child;
- thePreviousChild->m_Sibling != &inElement && thePreviousChild;
- thePreviousChild = thePreviousChild->m_Sibling) {
- }
- if (thePreviousChild)
- thePreviousChild->m_Sibling = inElement.m_Sibling;
- }
- }
+ if (inElement.GetParent())
+ inElement.GetParent()->removeChild(&inElement);
m_HandleToElements.erase(inElement.m_Handle);
@@ -369,7 +351,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
newProp = (SPropertyDesc *)m_AutoAllocator.allocate(allocSize, "SPropertyDesc",
__FILE__, __LINE__, 0);
- newProp->m_Name = inName;
+ newProp->setName(inName);
// convert to appropriate type
if (thePropertyType == Q3DStudio::ERuntimeDataModelDataTypeFloat) {
@@ -377,7 +359,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
element.m_TypeDescription->m_TypeName, theWorkSpaceString,
element.m_TypeDescription->m_SubtypeName);
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_FLOAT);
Q3DStudio::UVariant theValue;
theValue.m_FLOAT = value;
@@ -389,7 +371,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
qt3ds::QT3DSVec2 value = theMetaData.GetPropertyValueVector2(
element.m_TypeDescription->m_TypeName, theWorkSpaceString,
element.m_TypeDescription->m_SubtypeName);
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_FLOAT);
Q3DStudio::UVariant theVarValue;
theVarValue.m_FLOAT = value[extIndex];
@@ -404,7 +386,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
element.m_TypeDescription->m_SubtypeName);
if (separateProperties) {
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_FLOAT);
Q3DStudio::UVariant theVarValue;
theVarValue.m_FLOAT = value[extIndex];
@@ -412,7 +394,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
SPropertyDesc(theWorkSpaceString, Q3DStudio::ATTRIBUTETYPE_FLOAT),
theVarValue));
} else {
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT3;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_FLOAT3);
Q3DStudio::UVariant theVarValue;
theVarValue.m_FLOAT3[0] = value[0];
@@ -429,7 +411,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
element.m_TypeDescription->m_TypeName, theWorkSpaceString,
element.m_TypeDescription->m_SubtypeName);
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_INT32;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_INT32);
Q3DStudio::UVariant theVarValue;
theVarValue.m_INT32 = value;
@@ -443,7 +425,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
element.m_TypeDescription->m_TypeName, theWorkSpaceString,
element.m_TypeDescription->m_SubtypeName);
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_BOOL;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_BOOL);
Q3DStudio::UVariant theVarValue;
theVarValue.m_INT32 = value;
@@ -456,7 +438,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
element.m_TypeDescription->m_TypeName, theWorkSpaceString,
element.m_TypeDescription->m_SubtypeName);
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_STRING;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_STRING);
CStringHandle theString = m_StringTable.GetHandle(theRuntimeStr->c_str());
Q3DStudio::UVariant theVarValue;
@@ -467,7 +449,7 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
theTypeDesc->m_DynamicProperties.push_back(*newProp);
} else {
- newProp->m_Type = Q3DStudio::ATTRIBUTETYPE_FLOAT;
+ newProp->setType(Q3DStudio::ATTRIBUTETYPE_FLOAT);
theTypeDesc->m_DynamicProperties.push_back(*newProp);
}
@@ -494,6 +476,19 @@ struct SElementAllocator : public qt3ds::runtime::IElementAllocator
return NULL;
}
+ SElement *FindElementById(CRegisteredString elementId) override
+ {
+ auto iter = m_HandleToElements.begin();
+ auto end = m_HandleToElements.end();
+ for (; iter != end; iter++) {
+ SElement *elem = iter->second;
+ auto *translator = static_cast<Qt3DSTranslator *>(elem->GetAssociation());
+ if (translator && translator->RenderObject().m_Id == elementId)
+ return elem;
+ }
+ return nullptr;
+ }
+
// Returns an element pointer that when added to the return value of load will be a valid
// element.
SElement *GetRemappedElementAddress(SElement *inElement) const override
@@ -539,7 +534,7 @@ bool STypeDesc::operator==(const STypeDesc &inOther) const
for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
const SPropertyDesc &lhs = m_Properties[idx];
const SPropertyDesc &rhs = inOther.m_Properties[idx];
- if (lhs.m_Name != rhs.m_Name || lhs.m_Type != rhs.m_Type)
+ if (lhs.name() != rhs.name() || lhs.type() != rhs.type())
return false;
}
return true;
@@ -551,7 +546,7 @@ Option<QT3DSU32> STypeDesc::FindProperty(QT3DSU32 inNameHash) const
{
for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
const SPropertyDesc &theDesc = m_Properties[idx];
- if (Q3DStudio::CHash::HashAttribute(theDesc.m_Name) == inNameHash)
+ if (theDesc.nameHash() == inNameHash)
return idx;
}
return Empty();
@@ -559,19 +554,15 @@ Option<QT3DSU32> STypeDesc::FindProperty(QT3DSU32 inNameHash) const
Option<QT3DSU32> STypeDesc::FindProperty(CRegisteredString inName) const
{
- for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
- const SPropertyDesc &theDesc = m_Properties[idx];
- if (theDesc.m_Name == inName)
- return idx;
- }
- return Empty();
+ const auto hash = Q3DStudio::CHash::HashAttribute(inName);
+ return FindProperty(hash);
}
Option<QT3DSU32> STypeDesc::FindDynamicProperty(QT3DSU32 inNameHash) const
{
for (QT3DSU32 idx = 0, end = m_DynamicProperties.size(); idx < end; ++idx) {
const SPropertyDesc &theDesc = m_DynamicProperties[idx];
- if (Q3DStudio::CHash::HashAttribute(theDesc.m_Name) == inNameHash)
+ if (theDesc.nameHash() == inNameHash)
return idx;
}
return Empty();
@@ -581,16 +572,29 @@ void STypeDesc::SetHashValue()
{
size_t typeDescHash = m_TypeName.hash() ^ m_SubtypeName.hash();
for (QT3DSU32 idx = 0, end = m_Properties.size(); idx < end; ++idx) {
- typeDescHash = typeDescHash ^ m_Properties[idx].m_Name.hash();
- typeDescHash = typeDescHash ^ eastl::hash<QT3DSU32>()(m_Properties[idx].m_Type);
+ typeDescHash = typeDescHash ^ m_Properties[idx].name().hash();
+ typeDescHash = typeDescHash ^ eastl::hash<QT3DSU32>()(m_Properties[idx].type());
}
// TODO check 64 bit compatibility
m_HashValue = (QT3DSU32)typeDescHash;
}
-QT3DSU32 SPropertyDesc::GetNameHash() const
+SPropertyDesc::SPropertyDesc(CRegisteredString inStr, Q3DStudio::EAttributeType inType)
+ : m_Name(inStr)
+ , m_nameHash(Q3DStudio::CHash::HashAttribute(inStr.c_str()))
+ , m_Type(inType)
+{
+}
+
+void SPropertyDesc::setName(CRegisteredString name)
{
- return Q3DStudio::CHash::HashAttribute(m_Name.c_str());
+ m_Name = name;
+ m_nameHash = Q3DStudio::CHash::HashAttribute(name.c_str());
+}
+
+QT3DSU32 SPropertyDesc::nameHash() const
+{
+ return m_nameHash;
}
Q3DStudio::SAttributeKey SPropertyDesc::GetAttributeKey() const
@@ -598,7 +602,7 @@ Q3DStudio::SAttributeKey SPropertyDesc::GetAttributeKey() const
Q3DStudio::SAttributeKey retval;
memZero(&retval, sizeof(retval));
retval.m_Type = m_Type;
- retval.m_Hash = GetNameHash();
+ retval.m_Hash = nameHash();
return retval;
}
@@ -644,10 +648,13 @@ void SElement::SetAttribute(const Q3DStudio::TAttributeHash inKey,
const Q3DStudio::UVariant inValue)
{
Option<TPropertyDescAndValuePtr> existing = FindProperty(inKey);
- if (existing.hasValue() == false) {
+ if (!existing.hasValue()) {
if (Q3DStudio::ATTRIBUTE_EYEBALL == inKey)
SetFlag(Q3DStudio::ELEMENTFLAG_EXPLICITACTIVE, inValue.m_INT32 ? true : false);
- return;
+ else
+ existing = FindDynamicProperty(inKey);
+ if (!existing.hasValue())
+ return;
}
SetAttribute(*existing, inValue);
}
@@ -667,9 +674,9 @@ void SElement::stopAnimations(QT3DSU32 propHash)
void SElement::SetAttribute(TPropertyDescAndValuePtr inKey, const Q3DStudio::UVariant inValue,
bool forceSet)
{
- Q3DStudio::EAttributeType theType = inKey.first.m_Type;
+ Q3DStudio::EAttributeType theType = inKey.first.type();
Q3DStudio::UVariant *currentValue = inKey.second;
- QT3DSU32 attHash = inKey.first.GetNameHash();
+ QT3DSU32 attHash = inKey.first.nameHash();
// If there is an active animation for this property, disable it. Otherwise the set value
// gets overwritten immediately as animation update takes place.
@@ -716,10 +723,44 @@ void SElement::SetAttribute(TPropertyDescAndValuePtr inKey, const Q3DStudio::UVa
SetDirty();
}
+void SElement::setParent(SElement *parent)
+{
+ if (m_Parent)
+ m_Parent->removeChild(this);
+ m_Parent = parent;
+ if (m_Parent)
+ m_Parent->addChild(this);
+}
+void SElement::addChild(SElement *child)
+{
+ m_children.insert(child->GetNameHash(), child);
+}
+
+void SElement::removeChild(SElement *child)
+{
+ auto key = m_children.key(child);
+ m_children.remove(key);
+}
+
+void SElement::updateChildName(SElement *child)
+{
+ auto key = m_children.key(child);
+ m_children.remove(key);
+ m_children.insert(child->GetNameHash(), child);
+}
+
+void SElement::setName(CRegisteredString name)
+{
+ m_Name = name;
+ m_nameHash = Q3DStudio::CHash::HashString(name);
+ if (m_Parent)
+ m_Parent->updateChildName(this);
+}
+
// SElement implementation
QT3DSU32 SElement::GetNameHash() const
{
- return Q3DStudio::CHash::HashString(m_Name.c_str());
+ return m_nameHash;
}
// Q3DStudio::CHash::HashAttribute
@@ -845,11 +886,7 @@ const SElement &SElement::GetComponentParent() const
SElement *SElement::FindChild(QT3DSU32 inNameHash)
{
- for (SElement *theChild = m_Child; theChild; theChild = theChild->m_Sibling) {
- if (theChild->GetNameHash() == inNameHash)
- return theChild;
- }
- return NULL;
+ return m_children.value(inNameHash);
}
Q3DStudio::TTimeUnit SElement::GetInnerTime() const
diff --git a/src/runtime/Qt3DSElementSystem.h b/src/runtime/Qt3DSElementSystem.h
index 4eda166..22cf66c 100644
--- a/src/runtime/Qt3DSElementSystem.h
+++ b/src/runtime/Qt3DSElementSystem.h
@@ -68,19 +68,23 @@ namespace runtime {
namespace element {
struct SPropertyDesc
{
+ private:
CRegisteredString m_Name;
+ QT3DSU32 m_nameHash;
Q3DStudio::EAttributeType m_Type;
+ public:
SPropertyDesc()
- : m_Type(Q3DStudio::ATTRIBUTETYPE_NONE)
- {
- }
- SPropertyDesc(CRegisteredString inStr, Q3DStudio::EAttributeType inType)
- : m_Name(inStr)
- , m_Type(inType)
+ : m_nameHash(0)
+ , m_Type(Q3DStudio::ATTRIBUTETYPE_NONE)
{
}
- QT3DSU32 GetNameHash() const; // CHash::HashAttribute
+ SPropertyDesc(CRegisteredString inStr, Q3DStudio::EAttributeType inType);
+ QT3DSU32 nameHash() const; // CHash::HashAttribute
Q3DStudio::SAttributeKey GetAttributeKey() const;
+ Q3DStudio::EAttributeType type() const { return m_Type; }
+ CRegisteredString name() const { return m_Name; }
+ void setName(CRegisteredString name);
+ void setType(Q3DStudio::EAttributeType type) { m_Type = type; };
};
struct STypeDesc
@@ -157,7 +161,7 @@ namespace runtime {
}
};
- struct SElement;
+ class SElement;
struct SActivationManagerNode
{
@@ -242,6 +246,10 @@ namespace runtime {
{
return this->operator&(Q3DStudio::ELEMENTFLAG_TIMELINE);
}
+ bool HasActivityAction() const
+ {
+ return this->operator&(Q3DStudio::ELEMENTFLAG_ACTIVITYACTIONENABLED);
+ }
};
typedef eastl::pair<SPropertyDesc, Q3DStudio::UVariant *> TPropertyDescAndValuePtr;
@@ -259,17 +267,19 @@ namespace runtime {
Q3DStudio::UVariant m_Data[4];
SPropertyValueGroup *m_NextNode;
SPropertyValueGroup()
- : m_NextNode(NULL)
+ : m_NextNode(nullptr)
{
for (QT3DSU32 idx = 0; idx < NumValues; ++idx)
m_Data[idx].m_INT32 = 0;
}
};
- struct SElement
+ class SElement
{
CRegisteredString m_Name; // const, do not set after creation.
CRegisteredString m_Path;
+ QT3DSU32 m_nameHash;
+ public:
const STypeDesc *m_TypeDescription; ///< static information created on load time
// The property values are in order described in the type description.
SPropertyValueGroup *m_PropertyValues;
@@ -283,29 +293,35 @@ namespace runtime {
QT3DSU32 m_Handle;
QT3DSU32 m_ScriptID; ///< Superfluous, could use handle to link to script representation
QT3DSU32 m_Depth; ///< Distance from this node to the root of the graph.
+ private:
SElement *m_Parent; ///< Parent element in activity graph
- SElement *m_Sibling; ///< Next sibling element in activity graph
- SElement *m_Child; ///< First child element in activity graph
+ QHash<QT3DSU32, SElement *> m_children;
+ public:
bool m_OnMaster = false;
void *m_Association; ///< Link to associated asset in scene
Q3DStudio::IPresentation *m_BelongedPresentation;
SActivationManagerNode m_ActivationManagerNode;
SElement(const STypeDesc &inDesc)
- : m_TypeDescription(&inDesc)
- , m_PropertyValues(NULL)
- , m_DynamicTypeDescription(NULL)
- , m_DynamicPropertyValues(NULL)
+ : m_nameHash(0)
+ , m_TypeDescription(&inDesc)
+ , m_PropertyValues(nullptr)
+ , m_DynamicTypeDescription(nullptr)
+ , m_DynamicPropertyValues(nullptr)
, m_Handle(0)
, m_ScriptID(0)
, m_Depth(0)
- , m_Parent(NULL)
- , m_Sibling(NULL)
- , m_Child(NULL)
- , m_Association(NULL)
- , m_BelongedPresentation(NULL)
+ , m_Parent(nullptr)
+ , m_Association(nullptr)
+ , m_BelongedPresentation(nullptr)
{
}
+ void updateChildName(SElement *child);
+ QList<SElement *> children() const { return m_children.values(); };
+ CRegisteredString name() const { return m_Name; }
+ CRegisteredString path() const { return m_Path; }
+ void setName(CRegisteredString name);
+ void setPath(CRegisteredString path) { m_Path = path; }
QT3DSU32 GetHandle() const { return m_Handle; }
const STypeDesc &GetTypeDescription() const { return *m_TypeDescription; }
void SetTypeDescription(const STypeDesc *inDesc) { m_TypeDescription = inDesc; }
@@ -356,7 +372,7 @@ namespace runtime {
if (theVal.hasValue())
return theVal->second;
}
- return NULL;
+ return nullptr;
}
const Q3DStudio::UVariant *FindPropertyValue(QT3DSU32 inNameHash) const
{
@@ -366,7 +382,7 @@ namespace runtime {
if (theVal.hasValue())
return theVal->second;
}
- return NULL;
+ return nullptr;
}
Q3DStudio::UVariant *FindPropertyValue(CRegisteredString inNameHash)
{
@@ -376,7 +392,7 @@ namespace runtime {
if (theVal.hasValue())
return theVal->second;
}
- return NULL;
+ return nullptr;
}
const Q3DStudio::UVariant *FindPropertyValue(CRegisteredString inNameHash) const
@@ -387,7 +403,7 @@ namespace runtime {
if (theVal.hasValue())
return theVal->second;
}
- return NULL;
+ return nullptr;
}
Option<TPropertyDescAndValuePtr> FindProperty(QT3DSU32 inNameHash)
@@ -407,12 +423,11 @@ namespace runtime {
return Empty();
}
+ void setParent(SElement *parent);
+ void addChild(SElement *child);
+ void removeChild(SElement *child);
SElement *GetParent() { return m_Parent; }
const SElement *GetParent() const { return m_Parent; }
- SElement *GetSibling() { return m_Sibling; }
- const SElement *GetSibling() const { return m_Sibling; }
- SElement *GetChild() { return m_Child; }
- const SElement *GetChild() const { return m_Child; }
CRegisteredString GetType() const { return m_TypeDescription->m_TypeName; }
bool IsComponent() const { return m_Flags.IsComponent(); }
@@ -445,6 +460,7 @@ namespace runtime {
bool GetActive() const { return m_Flags.IsActive(); }
// Return true if we are about to activate, but have not yet been activated
+ // Also returns true when dirty and already active
bool AboutToActivate() const
{
if (!IsDirty())
@@ -452,6 +468,28 @@ namespace runtime {
return IsExplicitActive();
}
+ // Return true if we are about to deactivate, but have not yet been deactivated
+ // Also returns true when dirty and already not active
+ bool AboutToDeactivate() const
+ {
+ if (!IsDirty())
+ return false;
+ return !IsExplicitActive();
+ }
+
+ bool IsAnyParentAboutToActivate()
+ {
+ SElement *parent = GetParent();
+ if (parent) {
+ bool isActivating = parent->AboutToActivate();
+ if (Depth() > 2 && !isActivating)
+ isActivating = parent->IsAnyParentAboutToActivate();
+
+ return isActivating;
+ }
+ return false;
+ }
+
void SetPickEnabled(bool inValue)
{
SetFlag(Q3DStudio::ELEMENTFLAG_PICKENABLED, inValue);
@@ -514,7 +552,7 @@ namespace runtime {
bool IsTimeActive() const
{
- if (m_Parent != NULL)
+ if (m_Parent != nullptr)
return m_ActivationManagerNode.m_Flags.IsTimeActive();
return true;
}
@@ -532,11 +570,9 @@ namespace runtime {
{
if (IsComponent())
components.push_back(this);
- SElement *child = m_Child;
- while (child) {
+ const auto list = children();
+ for (auto child : list)
child->findComponents(components);
- child = child->m_Sibling;
- }
}
// Sets animation on property to inactive.
@@ -569,15 +605,18 @@ namespace runtime {
}
};
- struct SComponent : public SElement
+ class SComponent : public SElement
{
Q3DStudio::SAlignedTimeUnit m_BeginTime;
Q3DStudio::SAlignedTimeUnit m_Duration;
// Slide related
+ public:
QT3DSU8 m_SlideCount; ///< Number of slides starting from base index
+ private:
QT3DSU8 m_CurrentSlide; ///< Current slide number
QT3DSU8 m_PreviousSlide; ///< Previous slide number
+ public:
SComponent(const STypeDesc &inDesc)
: SElement(inDesc)
, m_SlideCount(0)
@@ -621,6 +660,7 @@ namespace runtime {
CRegisteredString inName) = 0;
virtual element::SElement *FindElementByHandle(QT3DSU32 inElementHandle) = 0;
+ virtual element::SElement *FindElementById(CRegisteredString elementId) = 0;
// Returns an element pointer that when added to the return value of load will be a valid
// element.
virtual element::SElement *
diff --git a/src/runtime/Qt3DSIComponentManager.h b/src/runtime/Qt3DSIComponentManager.h
index 50afe05..8c5a085 100644
--- a/src/runtime/Qt3DSIComponentManager.h
+++ b/src/runtime/Qt3DSIComponentManager.h
@@ -122,8 +122,9 @@ public: // Slides
virtual const CHAR *GetCurrentSlideName(TElement *inComponent) = 0;
virtual void applyQueuedChanges(TElement *component) = 0;
virtual void queueChange(TElement *component, TElement *target, const char *attName,
- const char *value) = 0;
+ const char *value, TAttributeHash attrHash) = 0;
virtual bool hasSlideChangeQueued(TElement *component) = 0;
+ virtual bool clearSlideChangeQueued(TElement *component) = 0;
virtual void OnElementDeactivated(TElement *inElement) = 0;
@@ -136,9 +137,13 @@ public: // Slides
virtual bool HasComponentGotoSlideCommand(TElement *inElement) = 0;
virtual SComponentGotoSlideData GetComponentGotoSlideCommand(TElement *inElement) = 0;
virtual void ReleaseComponentGotoSlideCommand(TElement *inElement) = 0;
+ virtual bool HasComponentGotoTimeCommand(TElement *inElement) = 0;
+ virtual void SetupComponentGotoTimeCommand(TElement *inElement, TTimeUnit time, bool relative) = 0;
+ virtual void ReleaseComponentGotoTimeCommand(TElement *inElement) = 0;
+ virtual void ClearGotoTimeQueue() = 0;
public: // Time
- virtual void GoToTime(TElement *inComponent, const TTimeUnit inTime) = 0;
+ virtual void GoToTime(TElement *inComponent, const TTimeUnit inTime, bool relative) = 0;
virtual void SetPause(TElement *inComponent, const BOOL inPause) = 0;
virtual void SetTimePolicy(TElement *inComponent, const TTimeUnit inLoopDuration,
const UINT32 inRepetitions, const BOOL inPingPong,
diff --git a/src/runtime/Qt3DSIScene.h b/src/runtime/Qt3DSIScene.h
index f754196..38f705e 100644
--- a/src/runtime/Qt3DSIScene.h
+++ b/src/runtime/Qt3DSIScene.h
@@ -144,6 +144,8 @@ public: // Base Interface
virtual bool preferKtx() const = 0;
+ virtual bool flipCompressedTextures() const = 0;
+
virtual void GetActiveSubPresentations(QVector<qt3ds::foundation::CRegisteredString> &subs) = 0;
virtual qt3ds::NVAllocatorCallback &allocator() = 0;
diff --git a/src/runtime/Qt3DSIScriptBridge.h b/src/runtime/Qt3DSIScriptBridge.h
index f424aac..cb13fb2 100644
--- a/src/runtime/Qt3DSIScriptBridge.h
+++ b/src/runtime/Qt3DSIScriptBridge.h
@@ -38,6 +38,7 @@
#include <QtCore/qvariant.h>
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
+#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
class QQmlImageProviderBase;
@@ -165,8 +166,8 @@ public: // Elements
// Use inProvider to create a new table and associate with inElement: currently a render plugin
// element this mimics render plugin as an behavior element
virtual void SetTableForElement(TElement &inElement, IScriptTableProvider &inProvider) = 0;
- virtual void SetAttribute(TElement *element, const char *attName, const char *value) = 0;
- virtual void SetAttribute(const char *element, const char *attName, const char *value) = 0;
+ virtual void SetAttribute(TElement *element, const QString &attName, const char *value) = 0;
+ virtual void SetAttribute(const QString &element, const QString &attName, const char *value) = 0;
virtual void FireEvent(const char *element, const char *evtName) = 0;
virtual void SetDataInputValue(
const QString &name, const QVariant &value,
@@ -189,6 +190,8 @@ public: // Elements
qt3ds::render::IBufferManager *bufferManager) = 0;
virtual uint textureId(const QString &elementPath,
qt3ds::render::IQt3DSRenderer *renderer) = 0;
+ virtual uint textureId(const QString &elementPath, qt3ds::render::IQt3DSRenderer *renderer,
+ QSize &size, GLenum &format) = 0;
public: // Components
virtual void GotoSlide(const char *component, const char *slideName,
@@ -199,6 +202,7 @@ public: // Components
public: // Presentation
virtual void SetPresentationAttribute(const char *presId, const char *attName,
const char *attValue) = 0;
+ virtual void initializePresentationDataInputsAndOutputs(CPresentation &presentation) = 0;
public: // Multimedia
virtual bool PlaySoundFile(const char *soundPath) = 0;
diff --git a/src/runtime/Qt3DSInputEventTypes.h b/src/runtime/Qt3DSInputEventTypes.h
index 0b3c398..fcf1d23 100644
--- a/src/runtime/Qt3DSInputEventTypes.h
+++ b/src/runtime/Qt3DSInputEventTypes.h
@@ -46,6 +46,9 @@ const TEventCommandHash ON_MOUSEOUT = CHash::HashEventCommand("onMouseOut");
const TEventCommandHash ON_GROUPEDMOUSEOVER = CHash::HashEventCommand("onGroupedMouseOver");
const TEventCommandHash ON_GROUPEDMOUSEOUT = CHash::HashEventCommand("onGroupedMouseOut");
+const TEventCommandHash ON_ACTIVATE = CHash::HashEventCommand("onActivate");
+const TEventCommandHash ON_DEACTIVATE = CHash::HashEventCommand("onDeactivate");
+
// Crude hack to pretend mouse events are gesture events, since gesture events are all you
// can specify in studio.
// TODO: Fix properly, preferably by bringing back gesture support
diff --git a/src/runtime/Qt3DSKernelTypes.h b/src/runtime/Qt3DSKernelTypes.h
index 6af4ab7..2e6d769 100644
--- a/src/runtime/Qt3DSKernelTypes.h
+++ b/src/runtime/Qt3DSKernelTypes.h
@@ -38,8 +38,8 @@
namespace qt3ds {
namespace runtime {
namespace element {
- struct SElement;
- struct SComponent;
+ class SElement;
+ class SComponent;
}
}
}
@@ -143,7 +143,10 @@ enum EElementFlag {
// Flags used by the activation manager
ELEMENTFLAG_AMGR_TIMEACTIVE = 1 << 13, ///< Is the element alive according to time information
- ELEMENTFLAG_CONTROLLED_ACTIVE = 1 << 14 ///< Is the element alive based on datainput control
+ ELEMENTFLAG_CONTROLLED_ACTIVE = 1 << 14, ///< Is the element alive based on datainput control
+
+ ELEMENTFLAG_ACTIVITYACTIONENABLED = 1 << 15, ///< Activity changing action has been registered on this element
+
};
// Four byte aligned time unit structure.
diff --git a/src/runtime/Qt3DSLogicSystem.cpp b/src/runtime/Qt3DSLogicSystem.cpp
index 4a8341b..742764c 100644
--- a/src/runtime/Qt3DSLogicSystem.cpp
+++ b/src/runtime/Qt3DSLogicSystem.cpp
@@ -218,7 +218,7 @@ struct SLogicSystem : public ILogicSystem
if (logicIter != m_LogicKeys.end()) {
for (TLogicDataList::iterator listIter = logicIter->second.begin(),
listEnd = logicIter->second.end();
- listIter != listEnd; ++listIter)
+ listIter != listEnd; ++listIter) {
if (listIter->m_Id == inActionIndex) {
listIter->m_Active = inActive;
if (IApplication::isPickingEvent(logicIter->first.m_CommandHash)) {
@@ -226,8 +226,16 @@ struct SLogicSystem : public ILogicSystem
logicIter->first.m_ElementHandle);
if (theElement && inActive)
theElement->SetFlag(Q3DStudio::ELEMENTFLAG_PICKENABLED, true);
+ } else if (IApplication::isActivityEvent(logicIter->first.m_CommandHash)) {
+ SElement *theElement = inElemAllocator.FindElementByHandle(
+ logicIter->first.m_ElementHandle);
+ if (theElement && inActive) {
+ theElement->SetFlag(Q3DStudio::ELEMENTFLAG_ACTIVITYACTIONENABLED,
+ true);
+ }
}
}
+ }
}
}
}
diff --git a/src/runtime/Qt3DSPresentation.cpp b/src/runtime/Qt3DSPresentation.cpp
index 504e7b6..6baf3be 100644
--- a/src/runtime/Qt3DSPresentation.cpp
+++ b/src/runtime/Qt3DSPresentation.cpp
@@ -226,6 +226,7 @@ void CPresentation::PostUpdate(const TTimeUnit inGlobalTime)
}
m_PreviousGlobalTime = inGlobalTime;
+ m_ComponentManager.ClearGotoTimeQueue();
}
void CPresentation::NotifyDataOutputs()
@@ -237,16 +238,16 @@ void CPresentation::NotifyDataOutputs()
Q3DStudio::TElementList &dirtyList = GetFrameData().GetDirtyList();
for (int idx = 0, end = dirtyList.GetCount(); idx < end; ++idx) {
Q3DStudio::TElement &element = *dirtyList[idx];
- if (m_pathToDataOutMap.contains(element.m_Path)) {
- auto outDefIter = m_pathToDataOutMap.find(element.m_Path);
+ if (m_pathToDataOutMap.contains(element.path())) {
+ auto outDefIter = m_pathToDataOutMap.find(element.path());
- while (outDefIter != m_pathToDataOutMap.end() && outDefIter.key() == element.m_Path) {
+ while (outDefIter != m_pathToDataOutMap.end() && outDefIter.key() == element.path()) {
qt3ds::runtime::DataOutputDef &outDef = outDefIter.value();
// Get current value
Q3DStudio::UVariant value;
- qt3ds::QT3DSU32 attribHash
- = CHash::HashAttribute(outDef.observedAttribute.attributeName[0]);
+ qt3ds::QT3DSU32 attribHash = CHash::HashAttribute(
+ outDef.observedAttribute.attributeName[0].constData());
element.GetAttribute(attribHash, value);
QVariant qvar;
switch (outDef.observedAttribute.propertyType) {
@@ -439,7 +440,7 @@ void CPresentation::ProcessEventBubbling(SEventCommand &ioEvent, INT32 &ioEventC
// Event bubbling
if (ioEvent.m_BubbleUp) {
- TElement *theParent = ioEvent.m_Target->m_Parent;
+ TElement *theParent = ioEvent.m_Target->GetParent();
if (theParent) {
ioEvent.m_Target = theParent;
ProcessEvent(ioEvent, ioEventCount);
@@ -473,7 +474,11 @@ void CPresentation::ProcessCommand(const SEventCommand &inCommand)
} else if (inCommand.m_Type == COMMAND_PAUSE) {
GetComponentManager().SetPause(inCommand.m_Target, true);
} else if (inCommand.m_Type == COMMAND_GOTOTIME) {
- GetComponentManager().GoToTime(inCommand.m_Target, inCommand.m_Arg1.m_INT32);
+ GetComponentManager().SetupComponentGotoTimeCommand(inCommand.m_Target,
+ inCommand.m_Arg1.m_INT32,
+ inCommand.m_Arg2.m_INT32 > 0);
+ GetComponentManager().GoToTime(inCommand.m_Target, inCommand.m_Arg1.m_INT32,
+ inCommand.m_Arg2.m_INT32 > 0);
// Slide (Arg1 = slide index or slide name)
} else if (inCommand.m_Type == COMMAND_GOTOSLIDE) {
@@ -481,8 +486,11 @@ void CPresentation::ProcessCommand(const SEventCommand &inCommand)
IComponentManager &theManager(GetComponentManager());
Q3DStudio::SComponentGotoSlideData theGotoSlideData =
theManager.GetComponentGotoSlideCommand(inCommand.m_Target);
- if (theGotoSlideData.m_Slide > 0)
+ if (theGotoSlideData.m_Slide > 0) {
+ if (theManager.hasSlideChangeQueued(inCommand.m_Target))
+ theManager.clearSlideChangeQueued(inCommand.m_Target);
theManager.GotoSlideIndex(inCommand.m_Target, theGotoSlideData);
+ }
theManager.ReleaseComponentGotoSlideCommand(inCommand.m_Target);
} else if (inCommand.m_Type == COMMAND_GOTOSLIDENAME) {
@@ -513,7 +521,7 @@ void CPresentation::ProcessCommand(const SEventCommand &inCommand)
} else if (inCommand.m_Type == COMMAND_EMITSIGNAL) {
CRegisteredString nameStr = GetStringTable().HandleToStr(inCommand.m_Arg1.m_INT32);
m_Application->GetRuntimeFactoryCore().GetScriptEngineQml().ProcessSignal(this, inCommand);
- QString path = QString::fromLatin1(inCommand.m_Target->m_Path.c_str());
+ QString path = QString::fromLatin1(inCommand.m_Target->path().c_str());
QString name = QString::fromLatin1(nameStr.c_str());
signalProxy()->SigCustomSignal(path, name);
} else {
diff --git a/src/runtime/Qt3DSPresentation.h b/src/runtime/Qt3DSPresentation.h
index 5917d7b..8bb66ae 100644
--- a/src/runtime/Qt3DSPresentation.h
+++ b/src/runtime/Qt3DSPresentation.h
@@ -108,6 +108,7 @@ protected:
TTimeUnit m_Offset;
TTimeUnit m_LocalTime;
TTimeUnit m_PreviousGlobalTime;
+ int m_UIPVersion;
bool m_Paused;
bool m_OffsetInvalid;
bool m_Active;
@@ -220,6 +221,15 @@ public: // Full file paths
QString GetFilePath() const override;
QString getProjectPath() const override;
+ void setUIPVersion(int version) override
+ {
+ m_UIPVersion = version;
+ }
+ int getUIPVersion() const override
+ {
+ return m_UIPVersion;
+ }
+
private: // Disabled Copy Construction
CPresentation(CPresentation &);
CPresentation &operator=(const CPresentation &);
diff --git a/src/runtime/Qt3DSQmlElementHelper.cpp b/src/runtime/Qt3DSQmlElementHelper.cpp
index 1ddd1c8..77196ae 100644
--- a/src/runtime/Qt3DSQmlElementHelper.cpp
+++ b/src/runtime/Qt3DSQmlElementHelper.cpp
@@ -67,98 +67,79 @@ CQmlElementHelper::~CQmlElementHelper()
}
TElement *CQmlElementHelper::GetElement(qt3ds::runtime::IApplication &inApplication,
- IPresentation *inDefaultPresentation, const char *inPath,
+ IPresentation *inDefaultPresentation, const QString &inPath,
TElement *inStartElement)
{
- if (inPath == nullptr || *inPath == 0)
+ if (inPath.isNull())
return nullptr;
- const char *thePath(inPath);
- const char *theSubPath = nullptr;
- IPresentation *thePresentation = nullptr;
- size_t thePathLength = ::strlen(thePath) + 1;
- char *theToken =
- Q3DStudio_allocate_desc(CHAR, thePathLength, "Token:TempPath"); // Temporary token storage
- // Try to get the specified presentation
- theSubPath = ::strchr(thePath, PRESENTATION_DELIMITER);
- TElement *theElement = inStartElement;
- if (theSubPath != nullptr) {
- UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
-
- ::strncpy(theToken, thePath, theSubPathLength);
- theToken[theSubPathLength] = '\0';
- thePath = theSubPath + 1;
-
- const CHAR *thePresentationName = theToken;
+ int delimIndex = inPath.indexOf(QLatin1Char(PRESENTATION_DELIMITER));
+ IPresentation *thePresentation = nullptr;
+ QString path = inPath;
- thePresentation = inApplication.LoadAndGetPresentationById(thePresentationName);
+ TElement *theElement = inStartElement;
+ if (delimIndex > 0) {
+ thePresentation = inApplication.LoadAndGetPresentationById(path.left(delimIndex));
+ path = path.right(path.length() - delimIndex - 1);
}
+
if (thePresentation == nullptr)
thePresentation = inDefaultPresentation;
// Return nil if the inStartElement is not in the specified presentation
if (theElement != nullptr
- && (theSubPath == nullptr && theElement->GetBelongedPresentation() != thePresentation)) {
+ && (delimIndex < 0 && theElement->GetBelongedPresentation() != thePresentation)) {
thePresentation = theElement->GetBelongedPresentation();
}
if (thePresentation == nullptr)
return nullptr;
- TStringHash theName;
- INT32 theParseCounter = 0;
-
- while (thePath != nullptr && thePath[0] != '\0') {
- ++theParseCounter;
-
- // Do some strtok() work here
- theSubPath = ::strchr(thePath, NODE_DELIMITER);
- if (theSubPath) {
- UINT32 theSubPathLength = static_cast<UINT32>(theSubPath - thePath);
- Q3DStudio_ASSERT(theSubPathLength < thePathLength);
-
- ::strncpy(theToken, thePath, theSubPathLength);
- theToken[theSubPathLength] = '\0';
+ int curIdx = 0;
+ int nodeDelim;
+ int theParseCounter = 0;
+ bool last = false;
- thePath = theSubPath + 1;
- } else {
- ::strcpy(theToken, thePath);
- thePath = nullptr;
+ do {
+ nodeDelim = path.indexOf(QLatin1Char(NODE_DELIMITER), curIdx);
+ if (nodeDelim < 0) {
+ nodeDelim = path.length();
+ last = true;
}
- // Hash the token and do some element searching
- theName = CHash::HashString(theToken);
+ ++theParseCounter;
- if (theName == RESERVED_PARENT) {
+ auto name = CHash::HashString(path, curIdx, nodeDelim);
+ if (name == RESERVED_PARENT) {
if (theElement)
theElement = theElement->GetParent();
- } else if (theName == RESERVED_THIS) {
+ } else if (RESERVED_THIS == name) {
//Keep the original element if "this" wanted
} else {
- if (theName == RESERVED_SCENE && theParseCounter == 1)
- theElement =
- thePresentation->GetRoot(); // theElement is nullptr, so using absolute path
-
+ if (name == RESERVED_SCENE && theParseCounter == 1)
+ theElement = thePresentation->GetRoot();
else if (theElement)
- theElement = theElement->FindChild(theName); // Using relative path
+ theElement = theElement->FindChild(name);
}
-
if (!theElement)
- thePath = nullptr;
- } // while
+ break;
+
+ curIdx = nodeDelim + 1;
+ } while (!last);
- Q3DStudio_free(theToken, CHAR, thePathLength);
return theElement;
}
CQmlElementHelper::TypedAttributeAndValue CQmlElementHelper::getTypedAttributeAndValue(
- TElement *theElement, const char *theAttName, const void *value)
+ TElement *theElement, const char *theAttName, const void *value, TAttributeHash attrHash)
{
TypedAttributeAndValue retVal = { SAttributeKey(), UVariant() };
retVal.attribute.m_Hash = 0;
SAttributeKey theAttributeKey;
- theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
+ theAttributeKey.m_Hash = attrHash;
+ if (!attrHash)
+ theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
// Early out for our single 'read only' attribute
if (ATTRIBUTE_URI == theAttributeKey.m_Hash) {
@@ -184,8 +165,8 @@ CQmlElementHelper::TypedAttributeAndValue CQmlElementHelper::getTypedAttributeAn
retVal.value = theNewValue;
} else if (thePropertyInfo.hasValue()) {
UVariant theNewValue;
- QString name(thePropertyInfo->first.m_Name.c_str());
- EAttributeType theAttributeType = thePropertyInfo->first.m_Type;
+ QString name(thePropertyInfo->first.name().c_str());
+ EAttributeType theAttributeType = thePropertyInfo->first.type();
switch (theAttributeType) {
case ATTRIBUTETYPE_INT32:
case ATTRIBUTETYPE_HASH:
@@ -246,11 +227,47 @@ CQmlElementHelper::TypedAttributeAndValue CQmlElementHelper::getTypedAttributeAn
return retVal;
}
+bool CQmlElementHelper::EnsureAttribute(TElement *theElement, const char *theAttName,
+ TAttributeHash attrHash)
+{
+ SAttributeKey theAttributeKey;
+ theAttributeKey.m_Hash = attrHash;
+ if (!attrHash)
+ theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
+
+ if (theAttributeKey.m_Hash == ATTRIBUTE_EYEBALL || theAttributeKey.m_Hash == ATTRIBUTE_URI)
+ return false;
+
+ // first search if it is a static property
+ Option<qt3ds::runtime::element::TPropertyDescAndValuePtr> thePropertyInfo =
+ theElement->FindProperty(theAttributeKey.m_Hash);
+
+ // Do not create property for eyeball, it uses the explicit activity flag
+ if (!thePropertyInfo.hasValue()) {
+ // if not search in the dynamic properties
+ thePropertyInfo = theElement->FindDynamicProperty(theAttributeKey.m_Hash);
+ if (!thePropertyInfo.hasValue()) {
+ // create a new dynamic porperty
+ qt3ds::runtime::IElementAllocator &theElemAllocator(
+ theElement->GetBelongedPresentation()->GetApplication().GetElementAllocator());
+ qt3ds::foundation::IStringTable &theStringTable(
+ theElement->GetBelongedPresentation()->GetStringTable());
+ IRuntimeMetaData &theMetaData =
+ theElement->GetBelongedPresentation()->GetApplication().GetMetaData();
+ thePropertyInfo = theElemAllocator.CreateDynamicProperty(
+ theMetaData, *theElement, theStringTable.RegisterStr(theAttName));
+ }
+ }
+ return true;
+}
+
bool CQmlElementHelper::SetAttribute(TElement *theElement, const char *theAttName,
- const void *value)
+ const void *value, TAttributeHash attrHash)
{
SAttributeKey theAttributeKey;
- theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
+ theAttributeKey.m_Hash = attrHash;
+ if (!attrHash)
+ theAttributeKey.m_Hash = CHash::HashAttribute(theAttName);
bool force = false;
// Fail if trying to change the activation state of an object in another slide
@@ -295,8 +312,8 @@ bool CQmlElementHelper::SetAttribute(TElement *theElement, const char *theAttNam
}
}
- TypedAttributeAndValue attributeAndValue = getTypedAttributeAndValue(theElement, theAttName,
- value);
+ TypedAttributeAndValue attributeAndValue
+ = getTypedAttributeAndValue(theElement, theAttName, value, theAttributeKey.m_Hash);
if (attributeAndValue.attribute.m_Hash == 0)
return false;
@@ -308,6 +325,13 @@ bool CQmlElementHelper::SetAttribute(TElement *theElement, const char *theAttNam
else
return false;
+ if (attributeAndValue.attribute.m_Hash == Q3DStudio::ATTRIBUTE_SUBPRESENTATION) {
+ auto presentation = theElement->GetBelongedPresentation();
+ auto stringValue = presentation->GetStringTable().HandleToStr(
+ attributeAndValue.value.m_StringHandle);
+ presentation->GetApplication().LoadAndGetPresentationById(stringValue.c_str());
+ }
+
return true;
}
@@ -328,7 +352,7 @@ bool CQmlElementHelper::GetAttribute(TElement *inElement, const char *inAttribut
*(INT32 *)value = val;
} else if (thePropertyInfo.hasValue()) {
UVariant *theValuePtr = thePropertyInfo->second;
- EAttributeType theAttributeType = thePropertyInfo->first.m_Type;
+ EAttributeType theAttributeType = thePropertyInfo->first.type();
switch (theAttributeType) {
case ATTRIBUTETYPE_INT32:
case ATTRIBUTETYPE_HASH:
diff --git a/src/runtime/Qt3DSQmlElementHelper.h b/src/runtime/Qt3DSQmlElementHelper.h
index f516571..507be66 100644
--- a/src/runtime/Qt3DSQmlElementHelper.h
+++ b/src/runtime/Qt3DSQmlElementHelper.h
@@ -45,10 +45,13 @@ private:
public:
static TElement *GetElement(qt3ds::runtime::IApplication &inApplication,
- IPresentation *inDefaultPresentation, const char *inPath,
+ IPresentation *inDefaultPresentation, const QString &inPath,
TElement *inStartElement = NULL);
- static bool SetAttribute(TElement *inElement, const char *inAttribute, const void *value);
+ static bool SetAttribute(TElement *inElement, const char *inAttribute, const void *value,
+ TAttributeHash attrHash);
+ static bool EnsureAttribute(TElement *inElement, const char *inAttribute,
+ TAttributeHash attrHash);
static bool GetAttribute(TElement *inElement, const char *inAttribute, void *value);
struct TypedAttributeAndValue {
@@ -58,7 +61,8 @@ public:
static TypedAttributeAndValue getTypedAttributeAndValue(TElement *inElement,
const char *inAttribute,
- const void *value);
+ const void *value,
+ TAttributeHash attrHash);
};
}
diff --git a/src/runtime/Qt3DSQmlEngine.cpp b/src/runtime/Qt3DSQmlEngine.cpp
index 5ab5c10..c74d0c0 100644
--- a/src/runtime/Qt3DSQmlEngine.cpp
+++ b/src/runtime/Qt3DSQmlEngine.cpp
@@ -428,8 +428,8 @@ public:
void ProcessCustomCallback(IPresentation *, const SEventCommand &) override {}
void SetTableForElement(TElement &, IScriptTableProvider &) override {}
- void SetAttribute(TElement *target, const char *attName, const char *value) override;
- void SetAttribute(const char *element, const char *attName, const char *value) override;
+ void SetAttribute(TElement *target, const QString &attName, const char *value) override;
+ void SetAttribute(const QString &element, const QString &attName, const char *value) override;
bool GetAttribute(TElement *target, const char *attName, char *value) override;
bool GetAttribute(const char *element, const char *attName, char *value) override;
void FireEvent(const char *element, const char *evtName) override;
@@ -452,12 +452,15 @@ public:
qt3ds::render::IBufferManager *bufferManager) override;
uint textureId(const QString &elementPath,
qt3ds::render::IQt3DSRenderer *renderer) override;
+ uint textureId(const QString &elementPath, qt3ds::render::IQt3DSRenderer *renderer, QSize &size,
+ GLenum &format) override;
void GotoSlide(const char *component, const char *slideName,
const SScriptEngineGotoSlideArgs &inArgs) override;
void GotoSlideRelative(const char *, bool, bool, const SScriptEngineGotoSlideArgs &) override;
void SetPresentationAttribute(const char *, const char *, const char *) override;
+ void initializePresentationDataInputsAndOutputs(CPresentation &presentation);
// No need to implement here, as sound playing is done in Qt3DSViewerApp
bool PlaySoundFile(const char *) override { return false; }
@@ -472,7 +475,7 @@ public:
const SScriptEngineGotoSlideArgs &inArgs) override;
bool GetSlideInfo(const char *elementPath, int &currentIndex, int &previousIndex,
QString &currentName, QString &previousName) override;
- void GotoTime(const char *component, const Q3DStudio::FLOAT time) override;
+ void GotoTime(const char *component, const Q3DStudio::FLOAT time, bool relative) override;
bool RegisterCallback(Q3DStudio::UINT32 callbackType, const TScriptCallback inCallback,
void *inUserData) override;
void Shutdown(qt3ds::NVFoundationBase &inFoundation) override;
@@ -480,7 +483,7 @@ public:
private:
TElement *createMaterialContainer(TElement *parent, CPresentation *presentation);
void createComponent(QQmlComponent *component, TElement *element);
- TElement *getTarget(const char *component);
+ TElement *getTarget(const QString &component);
void listAllElements(TElement *root, QList<TElement *> &elements);
void initializeDataInputsInPresentation(CPresentation &presentation, bool isPrimary,
bool isDynamicAdd = false,
@@ -495,18 +498,6 @@ private:
TElement *elem);
bool getAttributeVector2(QVector<QByteArray> &outAttVec, const QByteArray &attName,
TElement *elem);
- // build and evaluate Evaluator datainput type expression
- QJSValue buildJSFunc(const QString &userFunc);
- // pass controller name for error reporting purposes
- QVariant callJSFunc(const QString &controllerName, qt3ds::runtime::DataInputDef &diDef,
- const QVariant::Type type);
- // matches all numeric datatypes so we do not get datatype mismatch when JS
- // decides to change result datatype (f.ex from double to int when result
- // fractional part for specific input values happens to be exactly zero)
- bool isMatchingDatatype(QVariant::Type resultType, QVariant::Type propertyType);
- // find out which datainputs are used in the expression
- QVector<QString> resolveDependentDatainputs(const QString &expression,
- const QString &controllerName);
// Methods to add element attributes to list for element creation
void addStringAttribute(qt3ds::foundation::IStringTable &strTable,
@@ -606,47 +597,66 @@ void CQmlEngineImpl::Initialize()
}
}
-bool queueAttributeChange(TElement *target, const char *attName, const char *value)
+bool allowInactiveAttributeChange(TAttributeHash attrHash)
+{
+ switch (attrHash) {
+ case ATTRIBUTE_SOURCEPATH:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+bool queueAttributeChange(TElement *target, const char *attName, const char *value,
+ TAttributeHash attrHash)
{
if (target->m_BelongedPresentation->GetActivityZone()) {
TElement *componentElement = target->GetActivityZone().GetItemTimeParent(*target);
TComponent *component = static_cast<TComponent *>(componentElement);
// Queue changes to elements inside components that have not been activated even once
- if (component->GetCurrentSlide() == 0) {
+ if (component->GetCurrentSlide() == 0 && !allowInactiveAttributeChange(attrHash)) {
IPresentation *presentation = target->GetBelongedPresentation();
+ CQmlElementHelper::EnsureAttribute(target, attName, attrHash);
presentation->GetComponentManager().queueChange(componentElement, target,
- attName, value);
+ attName, value, attrHash);
return true;
}
}
return false;
}
-void CQmlEngineImpl::SetAttribute(TElement *target, const char *attName, const char *value)
+void CQmlEngineImpl::SetAttribute(TElement *target, const QString &attName, const char *value)
{
QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
if (target) {
- if (!queueAttributeChange(target, attName, value)) {
- bool success = CQmlElementHelper::SetAttribute(target, attName, value);
+ QByteArray att = attName.toUtf8();
+ auto attrHash = CHash::HashAttribute(attName);
+ if (!queueAttributeChange(target, att.constData(), value, attrHash)) {
+ bool success = CQmlElementHelper::SetAttribute(target, att.constData(), value,
+ attrHash);
if (!success) {
qCCritical(qt3ds::INVALID_OPERATION)
<< "CQmlEngineImpl::SetAttribute: "
<< "failed to set attribute on element"
- << target->m_Path.c_str() << ":" << attName << ":" << value;
+ << target->path().c_str() << ":" << attName << ":" << value;
}
}
}
}
-void CQmlEngineImpl::SetAttribute(const char *element, const char *attName, const char *value)
+void CQmlEngineImpl::SetAttribute(const QString &element, const QString &attName, const char *value)
{
QML_ENGINE_MULTITHREAD_PROTECT_METHOD;
TElement *theTarget = getTarget(element);
if (theTarget) {
- if (!queueAttributeChange(theTarget, attName, value)) {
- bool success = CQmlElementHelper::SetAttribute(theTarget, attName, value);
+ QByteArray att = attName.toUtf8();
+ auto attrHash = CHash::HashAttribute(attName);
+ if (!queueAttributeChange(theTarget, att.constData(), value, attrHash)) {
+ bool success = CQmlElementHelper::SetAttribute(theTarget, att.constData(), value,
+ attrHash);
if (!success) {
qCCritical(qt3ds::INVALID_OPERATION)
<< "CQmlEngineImpl::SetAttribute: "
@@ -784,15 +794,9 @@ void CQmlEngineImpl::SetDataInputValue(
case ATTRIBUTETYPE_DATAINPUT_TIMELINE: {
// Quietly ignore other than number type data inputs when adjusting timeline
if (diDef.type == qt3ds::runtime::DataInOutTypeRangedNumber) {
- TTimeUnit endTime = 0;
- TElement *element = getTarget(ctrlElem.elementPath.constData());
- TComponent *component = static_cast<TComponent *>(element);
- endTime = component->GetTimePolicy().GetLoopingDuration();
-
- // Normalize the value to dataInput range
- qreal newTime = qreal(endTime) * (qreal(value.toFloat() - diDef.min)
+ qreal newTime = (qreal(value.toFloat() - diDef.min)
/ qreal(diDef.max - diDef.min));
- GotoTime(ctrlElem.elementPath.constData(), float(newTime / 1000.0));
+ GotoTime(ctrlElem.elementPath.constData(), float(newTime), true);
}
break;
}
@@ -810,9 +814,6 @@ void CQmlEngineImpl::SetDataInputValue(
// the incoming value is cast to target property type without checking.
// Caveat emptor.
- // For Evaluator, typecheck the JS evaluation result to see if it
- // matches with the target property.
-
// Handle ranged number similarly to generic float
// if it is bound to properties other
// than timeline animation i.e. disregard range min and max
@@ -822,8 +823,6 @@ void CQmlEngineImpl::SetDataInputValue(
|| diDef.type == qt3ds::runtime::DataInOutTypeRangedNumber
|| diDef.type == qt3ds::runtime::DataInOutTypeVariant) {
valueFloat = value.toFloat();
- } else if (diDef.type == qt3ds::runtime::DataInOutTypeEvaluator) {
- valueFloat = callJSFunc(name, diDef, QVariant::Type::Double).toFloat();
} else {
qWarning() << __FUNCTION__ << "Property type "
<< ctrlElem.propertyType
@@ -864,9 +863,6 @@ void CQmlEngineImpl::SetDataInputValue(
if (diDef.type == qt3ds::runtime::DataInOutTypeVector3
|| diDef.type == qt3ds::runtime::DataInOutTypeVariant) {
valueVec = value.value<QVector3D>();
- } else if (diDef.type == qt3ds::runtime::DataInOutTypeEvaluator) {
- const QVariant res = callJSFunc(name, diDef, QVariant::Type::Vector3D);
- valueVec = res.value<QVector3D>();
} else {
qWarning() << __FUNCTION__ << "Property type "
<< ctrlElem.propertyType
@@ -890,9 +886,6 @@ void CQmlEngineImpl::SetDataInputValue(
if (diDef.type == qt3ds::runtime::DataInOutTypeVector2
|| diDef.type == qt3ds::runtime::DataInOutTypeVariant) {
valueVec = value.value<QVector2D>();
- } else if (diDef.type == qt3ds::runtime::DataInOutTypeEvaluator) {
- const QVariant res = callJSFunc(name, diDef, QVariant::Type::Vector2D);
- valueVec = res.value<QVector2D>();
} else {
qWarning() << __FUNCTION__ << "Property type "
<< ctrlElem.propertyType
@@ -915,8 +908,6 @@ void CQmlEngineImpl::SetDataInputValue(
if (diDef.type == qt3ds::runtime::DataInOutTypeBoolean
|| diDef.type == qt3ds::runtime::DataInOutTypeVariant) {
valueBool = value.toBool();
- } else if (diDef.type == qt3ds::runtime::DataInOutTypeEvaluator) {
- valueBool = callJSFunc(name, diDef, QVariant::Type::Bool).toBool();
} else {
qWarning() << __FUNCTION__ << "Property type "
<< ctrlElem.propertyType
@@ -933,9 +924,9 @@ void CQmlEngineImpl::SetDataInputValue(
// on master slide, and whose visibility setting must be persistent over
// slide changes.
TElement *element = getTarget(ctrlElem.elementPath.constData());
- auto hash = CHash::HashAttribute(ctrlElem.attributeName.first().constData());
+ auto hash = CHash::HashAttribute(QString(ctrlElem.attributeName.first()));
- if (hash == Q3DStudio::ATTRIBUTE_EYEBALL && element->m_OnMaster) {
+ if (element && hash == Q3DStudio::ATTRIBUTE_EYEBALL && element->m_OnMaster) {
element->GetActivityZone().setControlled(*element);
element->SetControlledActive(valueBool);
}
@@ -950,9 +941,6 @@ void CQmlEngineImpl::SetDataInputValue(
|| diDef.type == qt3ds::runtime::DataInOutTypeFloat
|| diDef.type == qt3ds::runtime::DataInOutTypeVariant) {
valueStr = value.toString().toUtf8();
- } else if (diDef.type == qt3ds::runtime::DataInOutTypeEvaluator) {
- valueStr = callJSFunc(name, diDef, QVariant::Type::String)
- .toString().toUtf8();
} else {
qWarning() << __FUNCTION__ << "Property type "
<< ctrlElem.propertyType
@@ -972,17 +960,6 @@ void CQmlEngineImpl::SetDataInputValue(
break;
}
}
-
- // Trigger re-evaluation of Evaluator datainputs that use this datainput
- // as source data. Do this by calling setDataInputValue for evaluator
- // with the current set value of the Evaluator (_not_ the evaluator result)
- for (auto dependent : diDef.dependents) {
- // Dependent list also contains the name of this datainput if
- // the value of this datainput is used as source data. In this case
- // obviously do not cause infinite recursion.
- if (dependent != name)
- SetDataInputValue(dependent, diMap[dependent].value);
- }
break;
}
case qt3ds::runtime::DataInputValueRole::Max: { // switch (valueRole)
@@ -1103,14 +1080,14 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
// Make sure the name is not duplicate
TElement *existingChild
- = parentElement->FindChild(CHash::HashString(newElementNameBa.constData()));
+ = parentElement->FindChild(CHash::HashString(newElementName));
if (existingChild) {
error = QObject::tr("Element already exists: '%1'").arg(elementPaths[elementIndex]);
handleError();
return;
}
- const CRegisteredString regName = strTable.RegisterStr(newElementNameBa);
+ const CRegisteredString regName = strTable.RegisterStr(newElementName);
TPropertyDescAndValueList elementProperties;
CRegisteredString metaType;
const CRegisteredString elementSubType;
@@ -1190,7 +1167,7 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
regName, metaType, elementSubType,
toConstDataRef(elementProperties.data(), QT3DSU32(elementProperties.size())),
presentation, parentElement, false);
- newElem.m_Path = strTable.RegisterStr(localElementPath);
+ newElem.setPath(strTable.RegisterStr(localElementPath));
// Insert the new element into the correct slide
if (!slideSystem.addSlideElement(component, slideIndex, newElem, eyeBall)) {
@@ -1213,7 +1190,7 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
presentation, &newElem, false);
QString matElemPath = localElementPath + QLatin1String(".refmat");
- newMatElem.m_Path = strTable.RegisterStr(matElemPath);
+ newMatElem.setPath(strTable.RegisterStr(matElemPath));
if (!slideSystem.addSlideElement(component, slideIndex, newMatElem, eyeBall)) {
// Delete created element and material element if adding to slide failed
@@ -1230,10 +1207,11 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
TElement *container = rootElement->FindChild(CHash::HashString("__Container"));
TElement *firstChild = nullptr;
if (container) {
- TElement *nextChild = container->GetChild();
- firstChild = nextChild;
- while (nextChild) {
- QString childName = QString::fromUtf8(nextChild->m_Name);
+ auto children = container->children();
+ if (!children.isEmpty())
+ firstChild = children.first();
+ for (auto nextChild : children) {
+ QString childName = QString::fromUtf8(nextChild->name());
if (childName.endsWith(refMatName)) {
auto tr = static_cast<Qt3DSTranslator *>(
nextChild->GetAssociation());
@@ -1241,7 +1219,6 @@ void CQmlEngineImpl::createElements(const QString &parentElementPath, const QStr
&tr->RenderObject());
break;
}
- nextChild = nextChild->GetSibling();
}
}
@@ -1458,17 +1435,14 @@ void CQmlEngineImpl::createMaterials(const QString &subPresId,
materialInfo->materialProps.remove(pathStr);
// Check that the material doesn't already exist in container
- TElement *firstChild = nullptr;
- TElement *nextChild = container->GetChild();
- firstChild = nextChild;
- while (nextChild) {
- QString childName = QString::fromUtf8(nextChild->m_Name);
+ const auto children = container->children();
+ for (auto nextChild : children) {
+ QString childName = QString::fromUtf8(nextChild->name());
if (childName == materialInfo->materialName) {
error = QObject::tr("Material already exists in material container");
handleError();
return;
}
- nextChild = nextChild->GetSibling();
}
// Create material element in the container based on the material definition
@@ -1654,7 +1628,8 @@ void CQmlEngineImpl::createMaterials(const QString &subPresId,
if (isCustomMaterial) {
newMaterial = customMaterialSystem->CreateCustomMaterial(matClass, allocator);
newMaterial->m_Id = newMatId;
- auto dynObj = static_cast<qt3ds::render::SDynamicObject *>(newMaterial);
+ auto dynGraphObj = static_cast<qt3ds::render::SDynamicGraphObject *>(newMaterial);
+ auto dynObj = dynGraphObj->m_dynamicObject;
QHashIterator<QString, qt3ds::render::dynamic::SPropertyDefinition>
dynPropIter(dynPropDefs);
@@ -1700,7 +1675,23 @@ void CQmlEngineImpl::createMaterials(const QString &subPresId,
case qt3ds::render::NVRenderShaderDataTypes::NVRenderImage2DPtr: {
CRegisteredString regStr;
regStr = strTable.RegisterStr(propValStr);
- setDynamicObjectProperty(*dynObj, propDesc, regStr);
+ if (!regStr.IsValid())
+ break;
+
+ SImage *img = dynGraphObj->getImage(propDesc.m_Name);
+ if (!img) {
+ img = QT3DS_NEW(allocator, qt3ds::render::SImage)();
+ img->m_Id = strTable.RegisterStr(
+ QString::fromLatin1(newMatId.c_str()) + QLatin1Char('_')
+ + QString::fromLatin1(propDesc.m_Name.c_str()));
+ setDynamicObjectProperty(*dynObj, propDesc, img->m_Id);
+ dynGraphObj->setImage(propDesc.m_Name, img);
+ }
+ img->m_ImagePath = regStr;
+ img->m_MagFilter = propDesc.m_MagFilterOp;
+ img->m_MinFilter = propDesc.m_MinFilterOp;
+ img->m_HorizontalTilingMode = img->m_VerticalTilingMode = propDesc.m_CoordOp;
+ img->m_Flags.SetDirty(true);
break;
}
default:
@@ -1720,7 +1711,7 @@ void CQmlEngineImpl::createMaterials(const QString &subPresId,
while (imageIter.hasNext()) {
imageIter.next();
TElement *imageElem = imageIter.value();
- UVariant *propValue = newMatElem.FindPropertyValue(imageElem->m_Name);
+ UVariant *propValue = newMatElem.FindPropertyValue(imageElem->name());
if (propValue) {
propValue->m_ElementHandle = imageIter.value()->GetHandle();
@@ -1786,18 +1777,15 @@ void CQmlEngineImpl::deleteMaterials(const QStringList &materialNames, IQt3DSRen
QVector<TElement *> elementsToDelete;
const QList<QString> matNames = presMaterialMap.values(presId);
for (const auto &materialName : matNames) {
- TElement *firstChild = nullptr;
- TElement *nextChild = container->GetChild();
- firstChild = nextChild;
+ const auto children = container->children();
bool added = false;
- while (nextChild) {
- QString childName = QString::fromUtf8(nextChild->m_Name);
+ for (auto nextChild : children) {
+ QString childName = QString::fromUtf8(nextChild->name());
if (childName == materialName) {
elementsToDelete << nextChild;
added = true;
break;
}
- nextChild = nextChild->GetSibling();
}
if (!added) {
if (presId.isEmpty()) {
@@ -1840,23 +1828,70 @@ 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());
- if (image->m_TextureData.m_Texture) {
- return static_cast<uint>(reinterpret_cast<size_t>(
- image->m_TextureData.m_Texture->GetTextureObjectHandle()));
+ QSize size;
+ GLenum format;
+ return textureId(elementPath, renderer, size, format);
+}
+
+uint CQmlEngineImpl::textureId(const QString &elementPath, qt3ds::render::IQt3DSRenderer *renderer,
+ QSize &size, GLenum &format)
+{
+ auto subpresLayer = elementPath.split(QStringLiteral("::"));
+ if (subpresLayer.size() == 2) {
+ // This is true only for subpresentation layers
+ // First retrieve the main layer
+ TElement *mainPresentationLayer = getTarget(subpresLayer[0].toUtf8().constData());
+ if (!mainPresentationLayer)
+ return 0;
+ auto mainLayerTranslator = static_cast<qt3ds::render::Qt3DSTranslator *>(mainPresentationLayer->GetAssociation());
+ auto mainLayerTranslatorType = mainLayerTranslator->GetUIPType();
+ if (mainLayerTranslatorType != qt3ds::render::GraphObjectTypes::Layer)
+ return 0;
+ auto mainLayer = static_cast<qt3ds::render::SLayer *>(&mainLayerTranslator->RenderObject());
+
+ // Now retrieve the subpresentation layer being queried
+ TElement *subPresentationLayer = getTarget(subpresLayer[1].toUtf8().constData());
+ if (!subPresentationLayer)
+ return 0;
+ auto subpresLayerTranslator = static_cast<qt3ds::render::Qt3DSTranslator *>(subPresentationLayer->GetAssociation());
+ auto subpresLayerTranslatorType = subpresLayerTranslator->GetUIPType();
+ if (subpresLayerTranslatorType != qt3ds::render::GraphObjectTypes::Layer)
+ return 0;
+ auto subpresLayer = static_cast<qt3ds::render::SLayer *>(&subpresLayerTranslator->RenderObject());
+
+ auto texdetails = renderer->getLayerTextureDetails(*subpresLayer, mainLayer);
+ size = QSize(texdetails.m_Width, texdetails.m_Height);
+ // Assume that NVRenderTextureFormats enums match GL texture format enums
+ format = renderer->getTextureGlFormat(texdetails.m_Format);
+ return renderer->getLayerTextureId(*subpresLayer, mainLayer);
+ } else {
+ TElement *elem = getTarget(elementPath.toUtf8().constData());
+ if (elem) {
+ auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(elem->GetAssociation());
+ if (translator) {
+ qt3ds::render::GraphObjectTypes::Enum elemType = translator->GetUIPType();
+ if (elemType == qt3ds::render::GraphObjectTypes::Layer) {
+ auto layer = static_cast<qt3ds::render::SLayer *>(&translator->RenderObject());
+ auto texdetails = renderer->getLayerTextureDetails(*layer);
+ size = QSize(texdetails.m_Width, texdetails.m_Height);
+ // Assume that NVRenderTextureFormats enums match GL texture format enums
+ format = renderer->getTextureGlFormat(texdetails.m_Format);
+ return renderer->getLayerTextureId(*layer);
+ } else if (elemType == qt3ds::render::GraphObjectTypes::Image) {
+ auto image = static_cast<qt3ds::render::SImage *>(&translator->RenderObject());
+ if (image->m_TextureData.m_Texture) {
+ auto texdetails = image->m_TextureData.m_Texture->GetTextureDetails();
+ size = QSize(texdetails.m_Width, texdetails.m_Height);
+ format = renderer->getTextureGlFormat(texdetails.m_Format);
+ return static_cast<uint>(reinterpret_cast<size_t>(
+ image->m_TextureData.m_Texture->GetTextureObjectHandle()));
+ }
}
}
}
}
+ size = {};
+ format = GL_INVALID_ENUM;
return 0;
}
@@ -1920,6 +1955,12 @@ void CQmlEngineImpl::SetPresentationAttribute(const char *presId, const char *,
}
}
+void CQmlEngineImpl::initializePresentationDataInputsAndOutputs(CPresentation &presentation)
+{
+ initializeDataInputsInPresentation(presentation, false);
+ initializeDataOutputsInPresentation(presentation, false);
+}
+
void CQmlEngineImpl::GotoSlideIndex(const char *component, const Q3DStudio::INT32 slideIndex,
const SScriptEngineGotoSlideArgs &inArgs)
{
@@ -1965,19 +2006,22 @@ bool CQmlEngineImpl::GetSlideInfo(const char *element, int &currentIndex, int &p
return false;
}
-void CQmlEngineImpl::GotoTime(const char *component, const Q3DStudio::FLOAT time)
+void CQmlEngineImpl::GotoTime(const char *component, const Q3DStudio::FLOAT time, bool relative)
{
TElement *theTarget = getTarget(component);
- if (theTarget && (theTarget->GetActive() || theTarget->AboutToActivate())) {
+ if (theTarget) {
UVariant theArg1;
UVariant theArg2;
-
IPresentation *thePresentation = theTarget->GetBelongedPresentation();
theArg1.m_INT32 = static_cast<INT32>(time * 1000);
+ theArg2.m_INT32 = relative ? 1 : 0;
TElement *theParentTarget = &theTarget->GetComponentParent();
+ thePresentation->GetComponentManager().SetupComponentGotoTimeCommand(theTarget,
+ theArg1.m_INT32,
+ relative);
thePresentation->FireCommand(COMMAND_GOTOTIME, theParentTarget, &theArg1, &theArg2);
}
}
@@ -2105,19 +2149,19 @@ void CQmlEngineImpl::createComponent(QQmlComponent *component, TElement *element
m_scripts.push_back(script);
}
-TElement *CQmlEngineImpl::getTarget(const char *component) {
+TElement *CQmlEngineImpl::getTarget(const QString &component) {
TElement *target = NULL;
- QStringList split = QString(component).split(":");
- if (split.size() > 1) {
+ int delimIndex = component.indexOf(":");
+ if (delimIndex > 0) {
target = CQmlElementHelper::GetElement(
*m_Application,
- m_Application->LoadAndGetPresentationById(split.at(0).toStdString().c_str()),
- split.at(1).toStdString().c_str(), NULL);
+ m_Application->LoadAndGetPresentationById(component.left(delimIndex)),
+ component.right(component.length() - delimIndex - 1), NULL);
} else {
target = CQmlElementHelper::GetElement(
*m_Application,
m_Application->GetPrimaryPresentation(),
- split.at(0).toStdString().c_str(), NULL);
+ component, NULL);
}
return target;
}
@@ -2125,11 +2169,9 @@ TElement *CQmlEngineImpl::getTarget(const char *component) {
void CQmlEngineImpl::listAllElements(TElement *root, QList<TElement *> &elements)
{
elements.append(root);
- TElement *nextChild = root->GetChild();
- while (nextChild) {
+ const auto children(root->children());
+ for (auto nextChild : children)
listAllElements(nextChild, elements);
- nextChild = nextChild->GetSibling();
- }
}
// Initializes datainput bindings in the presentation starting by default from the root element.
@@ -2138,6 +2180,9 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
bool isPrimary, bool isDynamicAdd,
QList<TElement *> inElements)
{
+ if (!m_Application)
+ return;
+
QList<TElement *> elements;
if (!inElements.empty()) {
elements = inElements;
@@ -2178,11 +2223,11 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
if (ctrlElem.attributeName.first() == QByteArrayLiteral("@timeline")) {
ctrlElem.propertyType = ATTRIBUTETYPE_DATAINPUT_TIMELINE;
TElement *component = &element->GetComponentParent();
- ctrlElem.elementPath.append(component->m_Path);
+ ctrlElem.elementPath.append(component->path());
} else if (ctrlElem.attributeName.first() == QByteArrayLiteral("@slide")) {
ctrlElem.propertyType = ATTRIBUTETYPE_DATAINPUT_SLIDE;
TElement *component = &element->GetComponentParent();
- ctrlElem.elementPath.append(component->m_Path);
+ ctrlElem.elementPath.append(component->path());
} else if (diMap[controllerName].type
== qt3ds::runtime::DataInOutTypeVector4) {
// special handling for vector datatype to handle
@@ -2193,7 +2238,7 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
element);
if (!attVec.empty() && success) {
ctrlElem.attributeName = attVec;
- ctrlElem.elementPath.append(element->m_Path);
+ ctrlElem.elementPath.append(element->path());
ctrlElem.propertyType = ATTRIBUTETYPE_FLOAT4;
} else {
qWarning() << __FUNCTION__ << "Property "
@@ -2211,7 +2256,7 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
element);
if (!attVec.empty() && success) {
ctrlElem.attributeName = attVec;
- ctrlElem.elementPath.append(element->m_Path);
+ ctrlElem.elementPath.append(element->path());
ctrlElem.propertyType = ATTRIBUTETYPE_FLOAT3;
} else {
qWarning() << __FUNCTION__ << "Property "
@@ -2229,7 +2274,7 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
element);
if (!attVec.empty() && success) {
ctrlElem.attributeName = attVec;
- ctrlElem.elementPath.append(element->m_Path);
+ ctrlElem.elementPath.append(element->path());
ctrlElem.propertyType = ATTRIBUTETYPE_FLOAT2;
} else {
qWarning() << __FUNCTION__ << "Property "
@@ -2237,34 +2282,15 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
<< " was not expanded to vector";
ctrlElem.propertyType = ATTRIBUTETYPE_NONE;
}
- } else if (diMap[controllerName].type
- == qt3ds::runtime::DataInOutTypeEvaluator) {
- diMap[controllerName].evalFunc
- = buildJSFunc(diMap[controllerName].evaluator);
- auto referencedDIs = resolveDependentDatainputs(
- diMap[controllerName].evaluator, controllerName);
- // add this evaluator datainput to the dependent list
- // for those datainputs that are used in the expression
- // for this evaluator
- for (auto ref : referencedDIs)
- diMap[ref].dependents.append(controllerName);
-
- ctrlElem.elementPath.append(element->m_Path);
- TStringHash attHash = CHash::HashAttribute(
- ctrlElem.attributeName.first().constData());
- Option<qt3ds::runtime::element::TPropertyDescAndValuePtr> attInfo
- = element->FindProperty(attHash);
- if (attInfo.hasValue())
- ctrlElem.propertyType = attInfo->first.m_Type;
} else {
// all other scalar datatypes
- ctrlElem.elementPath.append(element->m_Path);
+ ctrlElem.elementPath.append(element->path());
TStringHash attHash = CHash::HashAttribute(
- ctrlElem.attributeName.first().constData());
+ QString(ctrlElem.attributeName.first()));
Option<qt3ds::runtime::element::TPropertyDescAndValuePtr> attInfo
= element->FindProperty(attHash);
if (attInfo.hasValue()) {
- ctrlElem.propertyType = attInfo->first.m_Type;
+ ctrlElem.propertyType = attInfo->first.type();
} else {
ctrlElem.propertyType = ATTRIBUTETYPE_NONE;
qWarning() << __FUNCTION__ << "Property "
@@ -2332,6 +2358,9 @@ void CQmlEngineImpl::initializeDataInputsInPresentation(CPresentation &presentat
void CQmlEngineImpl::initializeDataOutputsInPresentation(CPresentation &presentation,
bool isPrimary)
{
+ if (!m_Application)
+ return;
+
TElement *parent = presentation.GetRoot();
QList<TElement *> elements;
listAllElements(parent, elements);
@@ -2372,7 +2401,7 @@ void CQmlEngineImpl::initializeDataOutputsInPresentation(CPresentation &presenta
// Timeline requires special additional handling
obsElem.propertyType = ATTRIBUTETYPE_DATAINPUT_TIMELINE;
TElement *component = &element->GetComponentParent();
- obsElem.elementPath.append(component->m_Path);
+ obsElem.elementPath.append(component->path());
// Find the TElement for the @timeline attrib
TElement *target = nullptr;
@@ -2395,13 +2424,13 @@ void CQmlEngineImpl::initializeDataOutputsInPresentation(CPresentation &presenta
// slide transitions
} else {
// Every other type is handled by CPresentation
- obsElem.elementPath.append(element->m_Path);
+ obsElem.elementPath.append(element->path());
TStringHash attHash = CHash::HashAttribute(
obsElem.attributeName.first().constData());
Option<qt3ds::runtime::element::TPropertyDescAndValuePtr> attInfo
= element->FindProperty(attHash);
if (attInfo.hasValue()) {
- obsElem.propertyType = attInfo->first.m_Type;
+ obsElem.propertyType = attInfo->first.type();
} else {
obsElem.propertyType = ATTRIBUTETYPE_NONE;
qWarning() << __FUNCTION__ << "Property"
@@ -2436,7 +2465,7 @@ void CQmlEngineImpl::removeDataInputControl(const QVector<TElement *> &inElement
while (diMapIter.hasNext()) {
diMapIter.next();
for (const auto &inOutAttr : qAsConst(diMapIter.value().controlledAttributes)) {
- if (inOutAttr.elementPath == QByteArray(elem->m_Path))
+ if (inOutAttr.elementPath == QByteArray(elem->path()))
elemAttrsToRemove.append({diMapIter.key(), inOutAttr});
}
}
@@ -2456,7 +2485,7 @@ bool CQmlEngineImpl::getAttributeVector4(QVector<QByteArray> &outAttVec,
const QByteArray &attName,
TElement *elem)
{
- auto hashName = Q3DStudio::CHash::HashAttribute(attName + ".x");
+ auto hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".x"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".x");
@@ -2465,7 +2494,7 @@ bool CQmlEngineImpl::getAttributeVector4(QVector<QByteArray> &outAttVec,
outAttVec.append(attName + ".w");
return true;
}
- hashName = Q3DStudio::CHash::HashAttribute(attName + ".r");
+ hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".r"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".r");
outAttVec.append(attName + ".g");
@@ -2480,7 +2509,7 @@ bool CQmlEngineImpl::getAttributeVector3(QVector<QByteArray> &outAttVec,
const QByteArray &attName,
TElement *elem)
{
- auto hashName = Q3DStudio::CHash::HashAttribute(attName + ".x");
+ auto hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".x"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".x");
@@ -2488,7 +2517,7 @@ bool CQmlEngineImpl::getAttributeVector3(QVector<QByteArray> &outAttVec,
outAttVec.append(attName + ".z");
return true;
}
- hashName = Q3DStudio::CHash::HashAttribute(attName + ".r");
+ hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".r"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".r");
outAttVec.append(attName + ".g");
@@ -2502,7 +2531,7 @@ bool CQmlEngineImpl::getAttributeVector2(QVector<QByteArray> &outAttVec,
const QByteArray &attName,
TElement *elem)
{
- auto hashName = Q3DStudio::CHash::HashAttribute(attName + ".x");
+ auto hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".x"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".x");
@@ -2510,7 +2539,7 @@ bool CQmlEngineImpl::getAttributeVector2(QVector<QByteArray> &outAttVec,
return true;
}
- hashName = Q3DStudio::CHash::HashAttribute(attName + ".u");
+ hashName = Q3DStudio::CHash::HashAttribute(QString(attName + ".u"));
if (!elem->FindProperty(hashName).isEmpty()) {
outAttVec.append(attName + ".u");
outAttVec.append(attName + ".v");
@@ -2519,109 +2548,6 @@ bool CQmlEngineImpl::getAttributeVector2(QVector<QByteArray> &outAttVec,
return false;
}
-QJSValue CQmlEngineImpl::buildJSFunc(const QString &userFunc)
-{
- auto res = this->m_engine->evaluate(userFunc);
- if (res.isError()) {
- qWarning() << __FUNCTION__
- << "Uncaught exception during datainput evaluation. Evaluator function" << userFunc;
- }
- return res;
-}
-
-QVariant CQmlEngineImpl::callJSFunc(const QString &controllerName,
- qt3ds::runtime::DataInputDef &diDef,
- const QVariant::Type type)
-{
- qt3ds::runtime::DataInputMap &diMap = m_Application->dataInputMap();
- QJSValueList args;
- QVector<QString> sourceDIs = resolveDependentDatainputs(diDef.evaluator, controllerName);
-
- // get the most recent set values for datainput sources (arguments) in the expression
- for (auto diVal : sourceDIs)
- args << this->m_engine->toScriptValue(diMap[diVal].value);
-
- if (diDef.evalFunc.isCallable()) {
- QJSValue res = diDef.evalFunc.call(args);
- if (res.isError()) {
- qWarning() << __FUNCTION__ << "Error during datainput" << controllerName
- << "evaluator call:" << res.toString() << "\nEvaluator function"
- << diDef.evaluator;
- return QVariant::Invalid;
- }
-
- QVariant ret = res.toVariant();
- if (ret.isValid() && isMatchingDatatype(ret.type(), type)) {
- // further check if the result is valid number
- if (ret.type() == QVariant::Double && qIsNaN(res.toNumber())) {
- qWarning() << __FUNCTION__ << "Datainput" << controllerName << "evaluator"
- << "result not a number (NaN)."
- << "\nEvaluator function" << diDef.evaluator;
- return QVariant::Invalid;
- } else {
- return ret;
- }
- } else {
- qWarning() << __FUNCTION__ << "Datainput" << controllerName << "evaluator"
- << "result not valid or matching with target attribute type. Result type"
- << QVariant::typeToName(ret.type()) << " target attribute type "
- << QVariant::typeToName(type) << "\nEvaluator function" << diDef.evaluator;
- }
- } else {
- qWarning() << __FUNCTION__ << "Datainput" << controllerName << "evaluator"
- << diDef.evaluator << " not valid callable";
- }
- return QVariant::Invalid;
-}
-
-bool CQmlEngineImpl::isMatchingDatatype(QVariant::Type resultType, QVariant::Type propertyType)
-{
- if (resultType == propertyType)
- return true;
- // Allow binding from numeric datainput to string target
- if ((resultType == QVariant::Double || resultType == QVariant::Int
- || resultType == QVariant::LongLong)
- && (propertyType == QVariant::Double || propertyType == QVariant::Int
- || propertyType == QVariant::LongLong || propertyType == QVariant::String)) {
- return true;
- }
- return false;
-}
-
-QVector<QString> CQmlEngineImpl::resolveDependentDatainputs(const QString &expression,
- const QString &controllerName)
-{
- QVector<QString> ret;
- qt3ds::runtime::DataInputMap &diMap = m_Application->dataInputMap();
- if (!expression.contains("function", Qt::CaseInsensitive)) {
- qWarning() << __FUNCTION__ << "Function keyword not found in datainput"
- << controllerName << "evaluator";
- return QVector<QString>();
- }
-
- int argListStart = expression.indexOf("function(") + 9;
- int argListStop = expression.indexOf(')', argListStart);
- QString argstr = expression.mid(argListStart , argListStop - argListStart);
- QStringList args = argstr.split(',');
-
- for (auto di : args) {
- auto diTrim = di.trimmed();
- if (diMap.contains(diTrim)) {
- if (diMap[diTrim].type == qt3ds::runtime::DataInOutTypeEvaluator
- && diTrim != controllerName) {
- qWarning() << __FUNCTION__ << "Invalid evaluator function in" << controllerName
- << ". Another evaluator is used as source data.";
- } else {
- ret.append(diTrim);
- }
- } else {
- qWarning() << __FUNCTION__ << "Evaluator in" << controllerName << "evaluator"
- << "is using unknown datainput" << diTrim << " as input argument name";
- }
- }
- return ret;
-}
-
void CQmlEngineImpl::addStringAttribute(IStringTable &strTable,
CQmlEngineImpl::TPropertyDescAndValueList &list,
const QString &inAttName, const QString &inValue)
@@ -2797,12 +2723,9 @@ void CQmlEngineImpl::deleteElements(const QVector<TElement *> &elements,
if (m_elementIdMap.contains(elem))
releaseId(m_elementIdMap.take(elem));
- TElement *child = elem->m_Child;
- while (child) {
- TElement *sibling = child->m_Sibling;
+ const auto children(elem->children());
+ for (auto child : children)
deleteRenderObjects(child);
- child = sibling;
- }
auto translator = static_cast<qt3ds::render::Qt3DSTranslator *>(elem->GetAssociation());
if (translator) {
@@ -2880,7 +2803,7 @@ void CQmlEngineImpl::setDynamicObjectProperty(qt3ds::render::SDynamicObject &mat
const dynamic::SPropertyDefinition &propDesc,
const TDataType &propValue)
{
- memCopy(material.GetDataSectionBegin() + propDesc.m_Offset, &propValue, sizeof(TDataType));
+ memCopy(material.GetDataSectionOffset(propDesc.m_Offset), &propValue, sizeof(TDataType));
}
/**
diff --git a/src/runtime/Qt3DSQmlEngine.h b/src/runtime/Qt3DSQmlEngine.h
index c515df1..8d40097 100644
--- a/src/runtime/Qt3DSQmlEngine.h
+++ b/src/runtime/Qt3DSQmlEngine.h
@@ -170,7 +170,7 @@ public: // Public functions but not functions on the script bridge
*
* @return none
*/
- virtual void GotoTime(const char *component, const Q3DStudio::FLOAT time) = 0;
+ virtual void GotoTime(const char *component, const Q3DStudio::FLOAT time, bool relative) = 0;
/**
* @brief Return values of an attribute
diff --git a/src/runtime/Qt3DSSlideSystem.cpp b/src/runtime/Qt3DSSlideSystem.cpp
index 32d5ea3..c830307 100644
--- a/src/runtime/Qt3DSSlideSystem.cpp
+++ b/src/runtime/Qt3DSSlideSystem.cpp
@@ -41,6 +41,8 @@
#include "Qt3DSHash.h"
#include "Qt3DSTimePolicy.h"
#include "foundation/Qt3DSIndexableLinkedList.h"
+#include "Qt3DSIPresentation.h"
+#include "Qt3DSPresentation.h"
using namespace qt3ds::runtime;
using namespace qt3ds::runtime::element;
@@ -223,6 +225,13 @@ struct SSlideSystem : public ISlideSystem
m_CurrentSlide->m_sourcePaths.push_back(QString::fromUtf8(path));
}
+ void AddSourcePath(SSlideKey key, const char8_t *path) override
+ {
+ auto slide = FindSlide(key);
+ if (slide)
+ slide->m_sourcePaths.push_back(QString::fromUtf8(path));
+ }
+
void AddSubPresentation(const char8_t *subpresentationId) override
{
if (m_CurrentSlide)
@@ -330,11 +339,9 @@ struct SSlideSystem : public ISlideSystem
void removeElementRecursive(SSlide *slide, element::SElement &inElement)
{
- element::SElement *child = inElement.m_Child;
- while (child) {
+ const auto children = inElement.children();
+ for (auto child : children)
removeElementRecursive(slide, *child);
- child = child->m_Sibling;
- }
SSlideElement *slideElement = slide->m_FirstElement;
SSlideElement *previousElement = nullptr;
@@ -524,6 +531,8 @@ struct SSlideSystem : public ISlideSystem
inActive = false;
inElement.Flags().SetExplicitActive(inActive);
+ if (inElement.IsComponent())
+ inElement.SetDirty();
// No need to update element properties when exiting slide
if (m_slideRollback)
diff --git a/src/runtime/Qt3DSSlideSystem.h b/src/runtime/Qt3DSSlideSystem.h
index ddde8ac..2d8e84b 100644
--- a/src/runtime/Qt3DSSlideSystem.h
+++ b/src/runtime/Qt3DSSlideSystem.h
@@ -135,6 +135,7 @@ namespace runtime {
virtual SSlideAnimAction *AddSlideAnimAction(bool inAnimation, QT3DSI32 inIndex,
bool inActive) = 0;
virtual void AddSourcePath(const char8_t *path) = 0;
+ virtual void AddSourcePath(SSlideKey key, const char8_t *path) = 0;
virtual void AddSubPresentation(const char8_t *subpresentationId) = 0;
virtual QVector<QString> GetSourcePaths(SSlideKey inKey) = 0;
virtual QVector<QString> GetSubPresentations(SSlideKey inKey) = 0;
diff --git a/src/runtime/q3dsqmlscript.cpp b/src/runtime/q3dsqmlscript.cpp
index 725c752..85a1a84 100644
--- a/src/runtime/q3dsqmlscript.cpp
+++ b/src/runtime/q3dsqmlscript.cpp
@@ -99,7 +99,7 @@ Q3DSQmlScript::Q3DSQmlScript(CQmlEngine &api, Q3DSQmlBehavior &object,
auto nameHash = CHash::HashAttribute(property.name());
Option<element::TPropertyDescAndValuePtr> value = behavior.FindProperty(nameHash);
if (value.hasValue()) {
- switch (value->first.m_Type) {
+ switch (value->first.type()) {
case ATTRIBUTETYPE_INT32:
case ATTRIBUTETYPE_HASH:
t = QVariant::Int;
@@ -235,7 +235,7 @@ Q3DSQmlScript::Q3DSQmlScript(CQmlEngine &api, Q3DSQmlBehavior &object,
std::function<void()> mapper;
auto nameHash = CHash::HashAttribute(property.name());
Option<element::TPropertyDescAndValuePtr> prop = behavior.FindProperty(nameHash);
- if (prop.hasValue() && prop->first.m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT2) {
+ if (prop.hasValue() && prop->first.type() == Q3DStudio::ATTRIBUTETYPE_FLOAT2) {
mapper = [&object, property, prop]() {
QVector2D vec;
Q3DStudio::UVariant *value = prop->second;
@@ -271,7 +271,7 @@ Q3DSQmlScript::Q3DSQmlScript(CQmlEngine &api, Q3DSQmlBehavior &object,
std::function<void()> mapper;
auto nameHash = CHash::HashAttribute(property.name());
Option<element::TPropertyDescAndValuePtr> prop = behavior.FindProperty(nameHash);
- if (prop.hasValue() && prop->first.m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT3) {
+ if (prop.hasValue() && prop->first.type() == Q3DStudio::ATTRIBUTETYPE_FLOAT3) {
mapper = [&object, property, prop]() {
QVector3D vec;
Q3DStudio::UVariant *value = prop->second;
@@ -314,7 +314,7 @@ Q3DSQmlScript::Q3DSQmlScript(CQmlEngine &api, Q3DSQmlBehavior &object,
std::function<void()> mapper;
auto nameHash = CHash::HashAttribute(property.name());
Option<element::TPropertyDescAndValuePtr> prop = behavior.FindProperty(nameHash);
- if (prop.hasValue() && prop->first.m_Type == Q3DStudio::ATTRIBUTETYPE_FLOAT4) {
+ if (prop.hasValue() && prop->first.type() == Q3DStudio::ATTRIBUTETYPE_FLOAT4) {
mapper = [&object, property, prop]() {
QVector4D vec;
Q3DStudio::UVariant *value = prop->second;
@@ -578,7 +578,7 @@ void Q3DSQmlScript::fireEvent(const QString &event)
{
if (!m_behavior.GetActive())
return;
- m_api.FireEvent(m_behavior.m_Path, event.toUtf8().constData());
+ m_api.FireEvent(m_behavior.path(), event.toUtf8().constData());
}
void Q3DSQmlScript::registerForEvent(const QString &event, const QJSValue &function)
@@ -720,7 +720,7 @@ QString Q3DSQmlScript::getParent(const QString &handle)
TElement *parent = element->GetParent();
if (!parent)
return "";
- return parent->m_Path.c_str();
+ return parent->path().c_str();
}
void Q3DSQmlScript::setDataInputValue(const QString &name, const QVariant &value,
diff --git a/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp b/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp
index d19c9f6..658c402 100644
--- a/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp
+++ b/src/runtimerender/Qt3DSDistanceFieldGlyphCache.cpp
@@ -59,9 +59,11 @@ Q3DSDistanceFieldGlyphCache::Q3DSDistanceFieldGlyphCache(
: QSGDistanceFieldGlyphCache(font)
, m_context(context)
{
- m_maxTextureSize = Q3DSDISTANCEFIELDGLYPHCACHE_MAXIMUM_TEXURE_SIZE;
+ m_maxTextureWidth = Q3DSDISTANCEFIELDGLYPHCACHE_MAXIMUM_TEXURE_SIZE;
loadPregeneratedCache(font);
+ if (m_textures.size() < m_maxTextureCount)
+ m_textures.resize(m_maxTextureCount);
}
Q3DSDistanceFieldGlyphCache::~Q3DSDistanceFieldGlyphCache()
@@ -71,16 +73,14 @@ Q3DSDistanceFieldGlyphCache::~Q3DSDistanceFieldGlyphCache()
delete m_areaAllocator;
}
-int Q3DSDistanceFieldGlyphCache::maxTextureSize() const
-{
- return m_maxTextureSize;
-}
-
Q3DSDistanceFieldGlyphCache::TextureInfo *Q3DSDistanceFieldGlyphCache::textureInfo(int index) const
{
- while (index >= m_textures.size())
- m_textures.append(TextureInfo());
- return &m_textures[index];
+ Q_ASSERT(index < m_textures.size());
+
+ if (index < m_textures.size())
+ return &m_textures[index];
+ else
+ return nullptr;
}
void Q3DSDistanceFieldGlyphCache::referenceGlyphs(const QSet<glyph_t> &glyphs)
@@ -145,7 +145,7 @@ void Q3DSDistanceFieldGlyphCache::storeGlyphs(const QList<QDistanceField> &glyph
TexCoord c = glyphTexCoord(glyphIndex);
TextureInfo *texInfo = m_glyphsTexture.value(glyphIndex);
- resizeTexture(texInfo, maxTextureSize(), texInfo->allocatedArea.height());
+ resizeTexture(texInfo, m_maxTextureWidth, texInfo->allocatedArea.height());
Q_ASSERT(!glyphTextures[texInfo].contains(glyphIndex));
glyphTextures[texInfo].append(glyphIndex);
@@ -187,15 +187,22 @@ void Q3DSDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
QList<GlyphPosition> glyphPositions;
QVector<glyph_t> glyphsToRender;
+ const int padding = Q3DSDISTANCEFIELDGLYPHCACHE_PADDING;
+ if (m_maxTextureHeight == 0) {
+ const qreal scaleFactor = qreal(1) / QT_DISTANCEFIELD_SCALE(m_doubleGlyphResolution);
+ // We need to add a buffer to avoid glyphs that overlap the border between two
+ // textures causing the height of the textures to extend beyond the limit.
+ m_maxTextureHeight = m_maxTextureWidth - (qCeil(m_referenceFont.pixelSize() * scaleFactor) + distanceFieldRadius() * 2 + padding * 2);
+ }
+
if (m_areaAllocator == nullptr) {
- m_areaAllocator = new QSGAreaAllocator(QSize(maxTextureSize(),
- m_maxTextureCount * maxTextureSize()));
+ m_areaAllocator = new QSGAreaAllocator(QSize(m_maxTextureWidth,
+ m_maxTextureCount * m_maxTextureHeight));
}
for (QSet<glyph_t>::const_iterator it = glyphs.constBegin(); it != glyphs.constEnd() ; ++it) {
glyph_t glyphIndex = *it;
- int padding = Q3DSDISTANCEFIELDGLYPHCACHE_PADDING;
QRectF boundingRect = glyphData(glyphIndex).boundingRect;
int glyphWidth = qCeil(boundingRect.width()) + distanceFieldRadius() * 2;
int glyphHeight = qCeil(boundingRect.height()) + distanceFieldRadius() * 2;
@@ -230,8 +237,8 @@ void Q3DSDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
continue;
}
- TextureInfo *tex = textureInfo(alloc.y() / maxTextureSize());
- alloc = QRect(alloc.x(), alloc.y() % maxTextureSize(), alloc.width(), alloc.height());
+ TextureInfo *tex = textureInfo(alloc.y() / m_maxTextureHeight);
+ alloc = QRect(alloc.x(), alloc.y() % m_maxTextureHeight, alloc.width(), alloc.height());
tex->allocatedArea |= alloc;
Q_ASSERT(tex->padding == padding || tex->padding < 0);
@@ -243,6 +250,7 @@ void Q3DSDistanceFieldGlyphCache::requestGlyphs(const QSet<glyph_t> &glyphs)
glyphPositions.append(p);
glyphsToRender.append(glyphIndex);
+
m_glyphsTexture.insert(glyphIndex, tex);
}
@@ -361,7 +369,7 @@ bool Q3DSDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
}
qreal pixelSize = qreal(Qtdf::fetch<quint16>(qtdfTableStart, Qtdf::pixelSize));
- m_maxTextureSize = int(Qtdf::fetch<quint32>(qtdfTableStart, Qtdf::textureSize));
+ m_maxTextureWidth = m_maxTextureHeight = int(Qtdf::fetch<quint32>(qtdfTableStart, Qtdf::textureSize));
m_doubleGlyphResolution = Qtdf::fetch<quint8>(qtdfTableStart, Qtdf::flags) == 1;
padding = Qtdf::fetch<quint8>(qtdfTableStart, Qtdf::headerPadding);
@@ -370,7 +378,7 @@ bool Q3DSDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
return false;
}
- if (m_maxTextureSize <= 0) {
+ if (m_maxTextureWidth <= 0) {
qWarning("Invalid texture size in '%s'", qPrintable(font.familyName()));
return false;
}
@@ -396,13 +404,15 @@ bool Q3DSDistanceFieldGlyphCache::loadPregeneratedCache(const QRawFont &font)
return false;
}
- if (m_areaAllocator->size().height() % m_maxTextureSize != 0) {
+ if (m_areaAllocator->size().height() % m_maxTextureHeight != 0) {
qWarning("Area allocator size mismatch in '%s'", qPrintable(font.familyName()));
return false;
}
- textureCount = m_areaAllocator->size().height() / m_maxTextureSize;
+ textureCount = m_areaAllocator->size().height() / m_maxTextureHeight;
m_maxTextureCount = qMax(m_maxTextureCount, textureCount);
+ if (m_textures.size() < m_maxTextureCount)
+ m_textures.resize(m_maxTextureCount);
const char *textureRecord = allocatorData;
for (int i = 0; i < textureCount; ++i, textureRecord += Qtdf::TextureRecordSize) {
diff --git a/src/runtimerender/Qt3DSDistanceFieldGlyphCache_p.h b/src/runtimerender/Qt3DSDistanceFieldGlyphCache_p.h
index fb4826e..1c550cc 100644
--- a/src/runtimerender/Qt3DSDistanceFieldGlyphCache_p.h
+++ b/src/runtimerender/Qt3DSDistanceFieldGlyphCache_p.h
@@ -54,10 +54,10 @@ class Q3DSDistanceFieldGlyphCache : public QSGDistanceFieldGlyphCache
{
public:
struct TextureInfo {
- qt3ds::render::NVRenderTexture2D *texture;
+ qt3ds::render::NVRenderTexture2D *texture = nullptr;
int padding = -1;
- QRect allocatedArea;
+ QRect allocatedArea = QRect(0, 0, 1, 1);
QImage copy;
};
@@ -84,13 +84,13 @@ private:
bool loadPregeneratedCache(const QRawFont &font);
TextureInfo *textureInfo(int index) const;
- int maxTextureSize() const;
void resizeTexture(TextureInfo *info, int width, int height);
void setTextureData(qt3ds::render::NVRenderTexture2D *texture, QImage &image);
QSGAreaAllocator *m_areaAllocator = nullptr;
- int m_maxTextureSize = 0;
- int m_maxTextureCount = 3;
+ int m_maxTextureWidth = 0;
+ int m_maxTextureHeight = 0;
+ int m_maxTextureCount = 4;
mutable QVector<TextureInfo> m_textures;
QHash<glyph_t, TextureInfo *> m_glyphsTexture;
diff --git a/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp b/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp
index cf80617..6378660 100644
--- a/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp
+++ b/src/runtimerender/Qt3DSDistanceFieldRenderer.cpp
@@ -97,27 +97,27 @@ void Q3DSDistanceFieldRenderer::EndFrame()
// Remove meshes for glyphs that weren't rendered last frame
NVAllocatorCallback &alloc = m_context->GetAllocator();
- QHash<size_t, QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>>::const_iterator
- glyphIt = m_glyphCache.constBegin();
- while (glyphIt != m_glyphCache.constEnd()) {
+ QHash<size_t, QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>>::iterator
+ glyphIt = m_glyphCache.begin();
+ while (glyphIt != m_glyphCache.end()) {
const size_t textHash = glyphIt.key();
if (!m_renderedTexts.contains(textHash))
- m_glyphCache.erase(glyphIt++);
+ glyphIt = m_glyphCache.erase(glyphIt);
else
- glyphIt++;
+ ++glyphIt;
}
- QHash<size_t, Q3DSDistanceFieldMesh>::const_iterator meshIt = m_meshCache.constBegin();
- while (meshIt != m_meshCache.constEnd()) {
+ QHash<size_t, Q3DSDistanceFieldMesh>::iterator meshIt = m_meshCache.begin();
+ while (meshIt != m_meshCache.end()) {
const size_t glyphHash = meshIt.key();
const Q3DSDistanceFieldMesh &mesh = meshIt.value();
if (!m_renderedGlyphs.contains(glyphHash)) {
NVDelete(alloc, mesh.vertexBuffer);
NVDelete(alloc, mesh.indexBuffer);
NVDelete(alloc, mesh.inputAssembler);
- m_meshCache.erase(meshIt++);
+ meshIt = m_meshCache.erase(meshIt);
} else {
- meshIt++;
+ ++meshIt;
}
}
@@ -134,22 +134,27 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo)
QVector2D boundingBox = QVector2D(textInfo.m_BoundingBox.x, textInfo.m_BoundingBox.y);
const float halfWidth = boundingBox.x() / 2.0f;
const float halfHeight = boundingBox.y() / 2.0f;
+
+ QVector2D center;
+ if (textInfo.m_VerticalAlignment == TextVerticalAlignment::Top)
+ center.setY(halfHeight);
+ else if (textInfo.m_VerticalAlignment == TextVerticalAlignment::Bottom)
+ center.setY(-halfHeight);
+
+ if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Left)
+ center.setX(halfWidth);
+ else if (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Right)
+ center.setX(-halfWidth);
+
bool hasValidBoundingBox = boundingBox.x() > 0 || boundingBox.y() > 0;
QRawFont font = m_fontDatabase.findFont(textInfo.m_Font.c_str());
qreal scaleFactor = font.pixelSize() / qreal(textInfo.m_FontSize);
- const float boundingWidth = (textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Left
- || textInfo.m_HorizontalAlignment == TextHorizontalAlignment::Right)
- ? halfWidth : boundingBox.x();
- const float boundingHeight = (textInfo.m_VerticalAlignment == TextVerticalAlignment::Top
- || textInfo.m_VerticalAlignment == TextVerticalAlignment::Bottom)
- ? halfHeight : boundingBox.y();
-
const qreal maximumWidth = boundingBox.isNull() ? qreal(0x01000000)
- : qreal(boundingWidth) * scaleFactor;
+ : qreal(boundingBox.x()) * scaleFactor;
const qreal maximumHeight = boundingBox.isNull() ? qreal(0x01000000)
- : qreal(boundingHeight) * scaleFactor;
+ : qreal(boundingBox.y()) * scaleFactor;
QTextLayout layout;
QTextOption option = layout.textOption();
@@ -177,6 +182,7 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo)
QString text = textInfo.m_Text.c_str();
text.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ text.replace(QLatin1String("<br>"), QString(QChar::LineSeparator));
qreal width;
qreal height;
@@ -218,6 +224,13 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo)
width = qMin(maximumWidth, qMax(width, textWidth));
height += layout.engine()->lines[line.lineNumber()].height().toReal();
+ // Windows seems to have leading taken into account already in descent, which is used
+ // to calculate height. Linux and Integrity do not, so we'll need to handle the
+ // negative leading here. On Windows the leading is not negative, as it has already
+ // been accounted for in the descent.
+ const QFixed leading = layout.engine()->lines[line.lineNumber()].leading;
+ if (leading < 0)
+ height += leading.toInt();
// Fast path for right elide
if (textInfo.m_Elide == TextElide::ElideRight
@@ -430,40 +443,47 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo)
float y1Clip = 1.0f;
float y2Clip = 1.0f;
+ float leftPos = -halfWidth + center.x();
+ float rightPos = halfWidth + center.x();
+ float topPos = -halfHeight + center.y();
+ float bottomPos = halfHeight + center.y();
+
if (hasValidBoundingBox) {
- if ((cx1 < -halfWidth && cx2 < -halfWidth)
- || (cx1 > halfWidth && cx2 > halfWidth)
- || (cy1 < -halfHeight && cy2 < -halfHeight)
- || (cy1 > halfHeight && cy2 > halfHeight)) {
+ if ((cx1 < leftPos && cx2 < leftPos)
+ || (cx1 > rightPos && cx2 > rightPos)
+ || (cy1 < topPos && cy2 < topPos)
+ || (cy1 > bottomPos && cy2 > bottomPos)) {
continue;
}
float xDiff = qAbs(cx1 - cx2);
float yDiff = qAbs(cy1 - cy2);
- if (cx1 < -halfWidth) {
- x1Clip = 1.0f - qAbs(cx1 - (-halfWidth)) / xDiff;
- cx1 = -halfWidth;
+ if (cx1 < leftPos) {
+ x1Clip = 1.0f - qAbs(cx1 - leftPos) / xDiff;
+ cx1 = leftPos;
}
- if (cx2 > halfWidth) {
- x2Clip = 1.0f - qAbs(cx2 - halfWidth) / xDiff;
- cx2 = halfWidth;
+ if (cx2 > rightPos) {
+ x2Clip = 1.0f - qAbs(cx2 - rightPos) / xDiff;
+ cx2 = rightPos;
}
- if (cy1 < -halfHeight) {
- y1Clip = 1.0f - qAbs(cy1 - (-halfHeight)) / yDiff;
- cy1 = -halfHeight;
+ if (cy1 < topPos) {
+ y1Clip = 1.0f - qAbs(cy1 - topPos) / yDiff;
+ cy1 = topPos;
}
- if (cy2 > halfHeight) {
- y2Clip = 1.0f - qAbs(cy2 - halfHeight) / yDiff;
- cy2 = halfHeight;
+ if (cy2 > bottomPos) {
+ y2Clip = 1.0f - qAbs(cy2 - bottomPos) / yDiff;
+ cy2 = bottomPos;
}
}
cy1 = -cy1;
cy2 = -cy2;
+ topPos = -topPos;
+ bottomPos = -bottomPos;
if (cx1 < minimum.x)
minimum.x = cx1;
@@ -488,14 +508,14 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo)
maximum.y = cy1;
if (hasValidBoundingBox) {
- if (maximum.x < halfWidth)
- maximum.x = halfWidth;
- if (minimum.x > -halfWidth)
- minimum.x = -halfWidth;
- if (maximum.y < halfHeight)
- maximum.y = halfHeight;
- if (minimum.y > -halfHeight)
- minimum.y = -halfHeight;
+ if (maximum.x < rightPos)
+ maximum.x = rightPos;
+ if (minimum.x > leftPos)
+ minimum.x = leftPos;
+ if (maximum.y < topPos)
+ maximum.y = topPos;
+ if (minimum.y > bottomPos)
+ minimum.y = bottomPos;
}
float tx1 = float(c.x + c.xMargin);
@@ -974,10 +994,12 @@ void Q3DSDistanceFieldRenderer::renderText(SText &text, const QT3DSMat44 &mvp)
glyphInfo.fontScale * float(m_pixelRatio), textColor);
}
- m_renderedGlyphs += glyphHashValue;
+ if (!m_renderedGlyphs.contains(glyphHashValue))
+ m_renderedGlyphs += glyphHashValue;
}
- m_renderedTexts += textHashValue;
+ if (!m_renderedTexts.contains(textHashValue))
+ m_renderedTexts += textHashValue;
text.m_Bounds = NVBounds3(minimum, maximum);
}
@@ -1001,9 +1023,20 @@ ITextRendererCore &ITextRendererCore::createDistanceFieldRenderer(NVFoundationBa
void Q3DSDistanceFieldRenderer::checkAndAddRenderedTexts(SText &text)
{
- auto hashVal = getTextHashValue(text);
- if (m_glyphCache.contains(hashVal))
- m_renderedTexts += hashVal;
+ auto textHashVal = getTextHashValue(text);
+ if (m_glyphCache.contains(textHashVal)) {
+ m_renderedTexts += textHashVal;
+
+ QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo> &glyphsPerTexture
+ = m_glyphCache[textHashVal];
+ QHash<Q3DSDistanceFieldGlyphCache::TextureInfo *, GlyphInfo>::const_iterator it;
+ for (it = glyphsPerTexture.constBegin(); it != glyphsPerTexture.constEnd(); ++it) {
+ const GlyphInfo &glyphInfo = it.value();
+ size_t glyphHashValue = getGlyphHashValue(glyphInfo);
+ if (m_meshCache.contains(glyphHashValue))
+ m_renderedGlyphs += glyphHashValue;
+ }
+ }
}
// Unused methods:
diff --git a/src/runtimerender/Qt3DSQtTextRenderer.cpp b/src/runtimerender/Qt3DSQtTextRenderer.cpp
index 8587c8b..5dea413 100644
--- a/src/runtimerender/Qt3DSQtTextRenderer.cpp
+++ b/src/runtimerender/Qt3DSQtTextRenderer.cpp
@@ -423,6 +423,13 @@ struct Qt3DSQtTextRenderer : public ITextRenderer
++lines;
lineList.append(QString::fromUtf8(lineStartItem, lineLen - chopAmount));
lineLen = 0;
+ } else if (lineLen > 3 && *item == '>' && *(item - 1) == 'r' && *(item - 2) == 'b'
+ && *(item - 3) == '<') {
+ int chopAmount = 4;
+
+ ++lines;
+ lineList.append(QString::fromUtf8(lineStartItem, lineLen - chopAmount));
+ lineLen = 0;
}
}
if (lineStartItem)
diff --git a/src/runtimerender/Qt3DSRenderContextCore.cpp b/src/runtimerender/Qt3DSRenderContextCore.cpp
index 50042d1..4d925a8 100644
--- a/src/runtimerender/Qt3DSRenderContextCore.cpp
+++ b/src/runtimerender/Qt3DSRenderContextCore.cpp
@@ -127,7 +127,8 @@ struct SRenderContextCore : public IQt3DSRenderContextCore
IPathManagerCore &GetPathManagerCore() override { return *m_PathManagerCore; }
IQt3DSRenderContext &CreateRenderContext(NVRenderContext &inContext,
const char8_t *inPrimitivesDirectory,
- bool delayedLoading) override;
+ bool delayedLoading,
+ void *signalProxy) override;
void SetTextRendererCore(ITextRendererCore &inRenderer) override { m_TextRenderer = inRenderer; }
ITextRendererCore *GetTextRendererCore() override { return m_TextRenderer.mPtr; }
void setDistanceFieldRenderer(ITextRendererCore &inRenderer) override
@@ -241,13 +242,15 @@ struct SRenderContext : public IQt3DSRenderContext
NVScopedRefCounted<IRenderList> m_RenderList;
QT3DSU32 m_FrameCount;
volatile QT3DSI32 mRefCount;
- // Viewport that this render context should use
- Option<NVRenderRect> m_Viewport;
+
QSize m_WindowDimensions;
ScaleModes::Enum m_ScaleMode;
StereoModes::Enum m_StereoMode;
StereoViews::Enum m_StereoView;
double m_StereoEyeSeparation;
+ double m_StereoEyeRotation;
+ bool m_StereoProgressiveEnabled;
+ int m_SkipFramesInterval;
bool m_WireframeMode;
bool m_subPresentationRenderInLayer;
Option<QT3DSVec4> m_SceneColor;
@@ -267,9 +270,11 @@ struct SRenderContext : public IQt3DSRenderContext
QPair<QT3DSF32, int> m_FPS;
bool m_AuthoringMode;
QVector<QT3DSF32> m_frameTimes;
+ void *m_SignalProxy;
SRenderContext(NVRenderContext &ctx, IQt3DSRenderContextCore &inCore,
- const char8_t *inApplicationDirectory, bool delayedLoading)
+ const char8_t *inApplicationDirectory, bool delayedLoading,
+ void *signalProxy)
: m_RenderContext(ctx)
, m_CoreContext(inCore)
, m_StringTable(ctx.GetStringTable())
@@ -289,6 +294,9 @@ struct SRenderContext : public IQt3DSRenderContext
, m_StereoMode(StereoModes::Mono)
, m_StereoView(StereoViews::Mono)
, m_StereoEyeSeparation(0.4)
+ , m_StereoEyeRotation(0.0)
+ , m_StereoProgressiveEnabled(false)
+ , m_SkipFramesInterval(0)
, m_WireframeMode(false)
, m_subPresentationRenderInLayer(false)
, m_matteEnabled(false)
@@ -297,6 +305,7 @@ struct SRenderContext : public IQt3DSRenderContext
, m_PresentationScale(0, 0)
, m_FPS(qMakePair(0.0, 0))
, m_AuthoringMode(false)
+ , m_SignalProxy(signalProxy)
{
m_BufferManager->enableReloadableResources(delayedLoading);
m_OffscreenRenderManager = IOffscreenRenderManager::CreateOffscreenRenderManager(
@@ -414,6 +423,8 @@ struct SRenderContext : public IQt3DSRenderContext
return m_frameTimes;
}
+ void *GetSignalProxy() override { return m_SignalProxy; }
+
bool IsAuthoringMode() override { return m_AuthoringMode; }
void SetAuthoringMode(bool inMode) override { m_AuthoringMode = inMode; }
@@ -474,13 +485,36 @@ struct SRenderContext : public IQt3DSRenderContext
double GetStereoEyeSeparation() const override { return m_StereoEyeSeparation; }
+ void SetStereoEyeRotation(double rotation) override
+ {
+ m_StereoEyeRotation = rotation;
+ }
+
+ double GetStereoEyeRotation() const override { return m_StereoEyeRotation; }
+
+ void SetStereoProgressiveEnabled(bool enabled) override
+ {
+ m_StereoProgressiveEnabled = enabled;
+ }
+
+ bool GetStereoProgressiveEnabled() const override {
+ return m_StereoProgressiveEnabled && (m_StereoMode == StereoModes::LeftRight
+ || m_StereoMode == StereoModes::TopBottom);
+ }
+
+ void SetSkipFramesInterval(int interval) override
+ {
+ m_SkipFramesInterval = interval;
+ }
+
+ int GetSkipFramesInterval() const override {
+ return m_SkipFramesInterval;
+ }
+
void SetWireframeMode(bool inEnable) override { m_WireframeMode = inEnable; }
bool GetWireframeMode() override { return m_WireframeMode; }
- void SetViewport(Option<NVRenderRect> inViewport) override { m_Viewport = inViewport; }
- Option<NVRenderRect> GetViewport() const override { return m_Viewport; }
-
IRenderWidgetContext &GetRenderWidgetContext() override
{
return m_Renderer->GetRenderWidgetContext();
@@ -533,11 +567,7 @@ struct SRenderContext : public IQt3DSRenderContext
NVRenderRect GetContextViewport() const override
{
NVRenderRect retval;
- if (m_Viewport.hasValue())
- retval = *m_Viewport;
- else
- retval = NVRenderRect(0, 0, m_WindowDimensions.width(), m_WindowDimensions.height());
-
+ retval = NVRenderRect(0, 0, m_WindowDimensions.width(), m_WindowDimensions.height());
return retval;
}
@@ -667,56 +697,54 @@ struct SRenderContext : public IQt3DSRenderContext
void BeginFrame(bool firstFrame) override
{
- m_PreRenderPresentationDimensions = m_PresentationDimensions;
- QSize thePresentationDimensions(m_PreRenderPresentationDimensions);
- NVRenderRect theContextViewport(GetContextViewport());
- m_PerFrameAllocator.reset();
- IRenderList &theRenderList(*m_RenderList);
- theRenderList.BeginFrame();
- if (m_Viewport.hasValue()) {
- theRenderList.SetScissorTestEnabled(true);
+ if (m_StereoView != StereoViews::Right) {
+ m_PreRenderPresentationDimensions = m_PresentationDimensions;
+ QSize thePresentationDimensions(m_PreRenderPresentationDimensions);
+ NVRenderRect theContextViewport(GetContextViewport());
+ m_PerFrameAllocator.reset();
+ IRenderList &theRenderList(*m_RenderList);
+ theRenderList.BeginFrame();
theRenderList.SetScissorRect(theContextViewport);
- } else {
theRenderList.SetScissorTestEnabled(false);
- }
- bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation;
- eastl::pair<NVRenderRect, NVRenderRect> thePresViewportAndOuterViewport =
- GetPresentationViewportAndOuterViewport();
- NVRenderRect theOuterViewport = thePresViewportAndOuterViewport.second;
- // Calculate the presentation viewport perhaps with the window width and height swapped.
- NVRenderRect thePresentationViewport = thePresViewportAndOuterViewport.first;
- m_PresentationViewport = thePresentationViewport;
- m_PresentationScale = QT3DSVec2(
- (QT3DSF32)thePresentationViewport.m_Width / (QT3DSF32)thePresentationDimensions.width(),
- (QT3DSF32)thePresentationViewport.m_Height / (QT3DSF32)thePresentationDimensions.height());
- QSize fboDimensions;
- if (thePresentationViewport.m_Width > 0 && thePresentationViewport.m_Height > 0) {
- if (renderOffscreen == false) {
- m_PresentationDimensions = QSize(thePresentationViewport.m_Width,
- thePresentationViewport.m_Height);
- m_RenderList->SetViewport(thePresentationViewport);
- if (thePresentationViewport.m_X || thePresentationViewport.m_Y
- || thePresentationViewport.m_Width != (QT3DSI32)theOuterViewport.m_Width
- || thePresentationViewport.m_Height != (QT3DSI32)theOuterViewport.m_Height) {
- m_RenderList->SetScissorRect(thePresentationViewport);
- m_RenderList->SetScissorTestEnabled(true);
+ bool renderOffscreen = m_Rotation != RenderRotationValues::NoRotation;
+ eastl::pair<NVRenderRect, NVRenderRect> thePresViewportAndOuterViewport =
+ GetPresentationViewportAndOuterViewport();
+ NVRenderRect theOuterViewport = thePresViewportAndOuterViewport.second;
+ // Calculate the presentation viewport perhaps with the window width and height swapped.
+ NVRenderRect thePresentationViewport = thePresViewportAndOuterViewport.first;
+ m_PresentationViewport = thePresentationViewport;
+ m_PresentationScale = QT3DSVec2(
+ (QT3DSF32)thePresentationViewport.m_Width / (QT3DSF32)thePresentationDimensions.width(),
+ (QT3DSF32)thePresentationViewport.m_Height / (QT3DSF32)thePresentationDimensions.height());
+ QSize fboDimensions;
+ if (thePresentationViewport.m_Width > 0 && thePresentationViewport.m_Height > 0) {
+ if (renderOffscreen == false) {
+ m_PresentationDimensions = QSize(thePresentationViewport.m_Width,
+ thePresentationViewport.m_Height);
+ m_RenderList->SetViewport(thePresentationViewport);
+ if (thePresentationViewport.m_X || thePresentationViewport.m_Y
+ || thePresentationViewport.m_Width != (QT3DSI32)theOuterViewport.m_Width
+ || thePresentationViewport.m_Height != (QT3DSI32)theOuterViewport.m_Height) {
+ m_RenderList->SetScissorRect(thePresentationViewport);
+ m_RenderList->SetScissorTestEnabled(true);
+ }
+ } else {
+ QT3DSU32 imageWidth = ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Width);
+ QT3DSU32 imageHeight =
+ ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Height);
+ fboDimensions = QSize(imageWidth, imageHeight);
+ m_PresentationDimensions = QSize(thePresentationViewport.m_Width,
+ thePresentationViewport.m_Height);
+ NVRenderRect theSceneViewport = NVRenderRect(0, 0, imageWidth, imageHeight);
+ m_RenderList->SetScissorTestEnabled(false);
+ m_RenderList->SetViewport(theSceneViewport);
}
- } else {
- QT3DSU32 imageWidth = ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Width);
- QT3DSU32 imageHeight =
- ITextRenderer::NextMultipleOf4(thePresentationViewport.m_Height);
- fboDimensions = QSize(imageWidth, imageHeight);
- m_PresentationDimensions = QSize(thePresentationViewport.m_Width,
- thePresentationViewport.m_Height);
- NVRenderRect theSceneViewport = NVRenderRect(0, 0, imageWidth, imageHeight);
- m_RenderList->SetScissorTestEnabled(false);
- m_RenderList->SetViewport(theSceneViewport);
}
- }
- m_BeginFrameResult = SBeginFrameResult(
- renderOffscreen, m_PresentationDimensions, m_RenderList->IsScissorTestEnabled(),
- m_RenderList->GetScissor(), m_RenderList->GetViewport(), fboDimensions);
+ m_BeginFrameResult = SBeginFrameResult(
+ renderOffscreen, m_PresentationDimensions, m_RenderList->IsScissorTestEnabled(),
+ m_RenderList->GetScissor(), m_RenderList->GetViewport(), fboDimensions);
+ }
m_Renderer->BeginFrame();
m_OffscreenRenderManager->BeginFrame();
@@ -724,15 +752,43 @@ struct SRenderContext : public IQt3DSRenderContext
m_TextRenderer->BeginFrame();
if (m_TextTextureCache)
m_TextTextureCache->BeginFrame();
- m_ImageBatchLoader->BeginFrame(firstFrame);
+ if (m_StereoView != StereoViews::Right)
+ m_ImageBatchLoader->BeginFrame(firstFrame);
}
QT3DSVec2 GetPresentationScaleFactor() const override { return m_PresentationScale; }
+ void adjustRectToStereoMode(NVRenderRect &rect)
+ {
+ if (m_StereoMode == StereoModes::LeftRight) {
+ if (m_StereoView == StereoViews::Left) {
+ rect = NVRenderRect(rect.m_X, rect.m_Y, rect.m_Width / 2,
+ rect.m_Height);
+ }
+ if (m_StereoView == StereoViews::Right) {
+ rect = NVRenderRect(rect.m_X + rect.m_Width / 2, rect.m_Y,
+ rect.m_Width / 2, rect.m_Height);
+ }
+ } else if (m_StereoMode == StereoModes::TopBottom) {
+ if (m_StereoView == StereoViews::Left) {
+ rect = NVRenderRect(rect.m_X, rect.m_Y + rect.m_Height / 2,
+ rect.m_Width, rect.m_Height / 2);
+ }
+ if (m_StereoView == StereoViews::Right) {
+ rect = NVRenderRect(rect.m_X, rect.m_Y,
+ rect.m_Width, rect.m_Height / 2);
+ }
+ }
+ }
+
virtual void SetupRenderTarget()
{
- NVRenderRect theContextViewport(GetContextViewport());
- if (m_Viewport.hasValue()) {
+ bool stereoProgressiveEnabled = GetStereoProgressiveEnabled();
+ // Clearing for matte / scene background
+ if (stereoProgressiveEnabled) {
+ // With progressive stereoscopic rendering needs to be adjusted to viewport
+ NVRenderRect theContextViewport(GetContextViewport());
+ adjustRectToStereoMode(theContextViewport);
m_RenderContext->SetScissorTestEnabled(true);
m_RenderContext->SetScissorRect(theContextViewport);
} else {
@@ -755,7 +811,10 @@ struct SRenderContext : public IQt3DSRenderContext
}
bool renderOffscreen = m_BeginFrameResult.m_RenderOffscreen;
m_RenderContext->SetViewport(m_BeginFrameResult.m_Viewport);
- m_RenderContext->SetScissorRect(m_BeginFrameResult.m_ScissorRect);
+ NVRenderRect scissorRect = m_BeginFrameResult.m_ScissorRect;
+ if (stereoProgressiveEnabled)
+ adjustRectToStereoMode(scissorRect);
+ m_RenderContext->SetScissorRect(scissorRect);
m_RenderContext->SetScissorTestEnabled(m_BeginFrameResult.m_ScissorTestEnabled);
if (m_PresentationViewport.m_Width > 0 && m_PresentationViewport.m_Height > 0) {
@@ -823,14 +882,21 @@ struct SRenderContext : public IQt3DSRenderContext
}
}
}
+ // Reset scissor rect to full viewport size
+ m_RenderContext->SetScissorRect(GetContextViewport());
+
}
void RunRenderTasks() override
{
+ m_RenderContext->resetStates();
m_RenderList->RunRenderTasks();
- // Don't (re)setup when rendering stereoscopic second (right) eye
- if (m_StereoView != StereoViews::Right)
+ // Don't (re)setup when rendering stereoscopic second (right) eye.
+ // Except in progressive mode, where each viewport needs to be cleared separately.
+ if (m_StereoView != StereoViews::Right
+ || GetStereoProgressiveEnabled()) {
SetupRenderTarget();
+ }
}
// Note this runs before EndFrame
@@ -912,11 +978,13 @@ struct SRenderContext : public IQt3DSRenderContext
IQt3DSRenderContext &SRenderContextCore::CreateRenderContext(NVRenderContext &inContext,
const char8_t *inPrimitivesDirectory,
- bool delayedLoading)
+ bool delayedLoading,
+ void *signalProxy)
{
return *QT3DS_NEW(m_Foundation.getAllocator(), SRenderContext)(inContext, *this,
inPrimitivesDirectory,
- delayedLoading);
+ delayedLoading,
+ signalProxy);
}
}
diff --git a/src/runtimerender/Qt3DSRenderContextCore.h b/src/runtimerender/Qt3DSRenderContextCore.h
index 670becc..bb5943e 100644
--- a/src/runtimerender/Qt3DSRenderContextCore.h
+++ b/src/runtimerender/Qt3DSRenderContextCore.h
@@ -100,7 +100,8 @@ namespace render {
// The render context maintains a reference to this object.
virtual IQt3DSRenderContext &CreateRenderContext(NVRenderContext &inContext,
const char8_t *inPrimitivesDirectory,
- bool delayedLoading) = 0;
+ bool delayedLoading,
+ void *signalProxy) = 0;
static IQt3DSRenderContextCore &Create(NVFoundationBase &fnd, IStringTable &strt);
static bool distanceFieldEnabled();
@@ -150,6 +151,7 @@ namespace render {
virtual void SetFPS(QPair<QT3DSF32, int> inFPS) = 0;
virtual void SetFrameTime(QT3DSF32 time) = 0;
virtual QVector<QT3DSF32> GetFrameTimes() const = 0;
+ virtual void *GetSignalProxy() = 0;
// Currently there are a few things that need to work differently
// in authoring mode vs. runtime. The particle effects, for instance
@@ -184,11 +186,6 @@ namespace render {
virtual void SetWindowDimensions(const QSize &inWindowDimensions) = 0;
virtual QSize GetWindowDimensions() = 0;
- // In addition to the window dimensions which really have to be set, you can optionally
- // set the viewport which will force the entire viewer to render specifically to this
- // viewport.
- virtual void SetViewport(Option<NVRenderRect> inViewport) = 0;
- virtual Option<NVRenderRect> GetViewport() const = 0;
virtual NVRenderRect GetContextViewport() const = 0;
// Only valid between calls to Begin,End.
virtual NVRenderRect GetPresentationViewport() const = 0;
@@ -203,6 +200,12 @@ namespace render {
virtual StereoViews::Enum GetStereoView() const = 0;
virtual void SetStereoEyeSeparation(double separation) = 0;
virtual double GetStereoEyeSeparation() const = 0;
+ virtual void SetStereoEyeRotation(double rotation) = 0;
+ virtual double GetStereoEyeRotation() const = 0;
+ virtual void SetStereoProgressiveEnabled(bool enabled) = 0;
+ virtual bool GetStereoProgressiveEnabled() const = 0;
+ virtual void SetSkipFramesInterval(int interval) = 0;
+ virtual int GetSkipFramesInterval() const = 0;
virtual void SetWireframeMode(bool inEnable) = 0;
virtual bool GetWireframeMode() = 0;
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
index 82a4d73..69b357d 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialShaderGenerator.cpp
@@ -155,10 +155,11 @@ struct SShaderGeneratorGeneratedShader
NVRenderShaderProgram &m_Shader;
// Specific properties we know the shader has to have.
NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
- NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ModelViewProjMatrix;
NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
NVRenderCachedShaderProperty<QT3DSMat33> m_NormalMatrix;
NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPos;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
NVRenderCachedShaderProperty<QT3DSMat44> m_ProjMatrix;
NVRenderCachedShaderProperty<QT3DSMat44> m_ViewportMatrix;
NVRenderCachedShaderProperty<QT3DSVec2> m_CamProperties;
@@ -199,11 +200,12 @@ struct SShaderGeneratorGeneratedShader
: m_Allocator(inContext.GetAllocator())
, m_Shader(inShader)
, m_ModelMatrix("model_matrix", inShader)
- , m_ViewProjMatrix("model_view_projection", inShader)
+ , m_ModelViewProjMatrix("model_view_projection", inShader)
, m_ViewMatrix("view_matrix", inShader)
, m_NormalMatrix("normal_matrix", inShader)
, m_CameraPos("camera_position", inShader)
- , m_ProjMatrix("view_projection_matrix", inShader)
+ , m_ViewProjMatrix("view_projection_matrix", inShader)
+ , m_ProjMatrix("projection_matrix", inShader)
, m_ViewportMatrix("viewport_matrix", inShader)
, m_CamProperties("camera_properties", inShader)
, m_DepthTexture("depth_sampler", inShader)
@@ -440,6 +442,12 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
inImage.m_Image.m_HorizontalTilingMode);
inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapT(
inImage.m_Image.m_VerticalTilingMode);
+ if (inImage.m_Image.m_MinFilter > NVRenderTextureMinifyingOp::Linear
+ && inImage.m_Image.m_TextureData.m_Texture->GetNumMipmaps() == 0) {
+ inImage.m_Image.m_TextureData.m_Texture->GenerateMipmaps();
+ }
+ inImage.m_Image.m_TextureData.m_Texture->SetMinFilter(inImage.m_Image.m_MinFilter);
+ inImage.m_Image.m_TextureData.m_Texture->SetMagFilter(inImage.m_Image.m_MagFilter);
theShaderProps.m_Sampler.Set(inImage.m_Image.m_TextureData.m_Texture);
theShaderProps.m_Offsets.Set(offsets);
@@ -489,6 +497,56 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
return pCB;
}
+ QStringList getParameters(const QString &str, int begin, int end)
+ {
+ const QString s = str.mid(begin, end - begin + 1);
+ return s.split(",");
+ }
+
+ void insertSnapperDirectives(QString &str)
+ {
+ int beginIndex = 0;
+ // Snapper macros:
+ // uniform sampler2D samplerName; \
+ // uniform vec3 samplerName##TransformU; \
+ // uniform vec3 samplerName##TransformV; \
+ // vec3 texcoordTransformed_##samplerName(vec3 coord) \
+ // { \
+ // return vec3(dot(samplerName##TransformU, coord), dot(samplerName##TransformV, coord), coord.z); \
+ // } \
+ // vec4 sampleTransformed_##samplerName(vec3 coord) \
+ // { \
+ // return texture(samplerName, texcoordTransformed_##samplerName(coord).xy); \
+ // }
+ QString snapperSampler = QStringLiteral("SNAPPER_SAMPLER2D(");
+ QString endingBracket = QStringLiteral(")");
+
+ const auto insertSnapperStr = [](const QString &parameter) {
+ QString insertStr;
+ QTextStream stream(&insertStr);
+ stream << "uniform sampler2D " << parameter << ";\n";
+ stream << "uniform vec3 " << parameter << "TransformU;\n";
+ stream << "uniform vec3 " << parameter << "TransformV;\n";
+ stream << "vec3 texcoordTransformed_" << parameter << "(vec3 coord) {"
+ << "return vec3(dot(" << parameter << "TransformU, coord), dot(" << parameter
+ << "TransformV, coord), coord.z); }";
+ stream << "vec4 sampleTransformed_" << parameter << "(vec3 coord)"
+ << "{ return texture(" << parameter << ", texcoordTransformed_" << parameter
+ << "(coord).xy); }";
+ return insertStr;
+ };
+
+ while ((beginIndex = str.indexOf(snapperSampler, beginIndex)) >= 0) {
+ int endIndex = str.indexOf(endingBracket, beginIndex);
+ const QStringList list = getParameters(str, beginIndex + snapperSampler.length(),
+ endIndex);
+ str.remove(beginIndex, endIndex - beginIndex + 1);
+ if (list.size() == 5)
+ str.insert(beginIndex, insertSnapperStr(list[0]));
+ }
+ }
+
+
bool GenerateVertexShader(SShaderDefaultMaterialKey &, const char8_t *inShaderPathName)
{
qt3ds::render::IDynamicObjectSystem &theDynamicSystem(
@@ -497,7 +555,9 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
theDynamicSystem.GetShaderSource(
m_RenderContext.GetStringTable().RegisterStr(inShaderPathName), theShaderBuffer);
- eastl::string srcString(theShaderBuffer.c_str());
+ QString str = QString::fromLatin1(theShaderBuffer.c_str());
+ insertSnapperDirectives(str);
+ eastl::string srcString(str.toLatin1().constData());
// Check if the vertex shader portion already contains a main function
// The same string contains both the vertex and the fragment shader
@@ -627,11 +687,13 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
if (theShader.m_ViewMatrix.IsValid())
theShader.m_ViewMatrix.Set(theCamera.m_GlobalTransform.getInverse());
+ if (theShader.m_ProjMatrix.IsValid())
+ theShader.m_ProjMatrix.Set(inCamera.m_Projection);
- if (theShader.m_ProjMatrix.IsValid()) {
+ if (theShader.m_ViewProjMatrix.IsValid()) {
QT3DSMat44 vProjMat;
inCamera.CalculateViewProjectionMatrix(vProjMat);
- theShader.m_ProjMatrix.Set(vProjMat);
+ theShader.m_ViewProjMatrix.Set(vProjMat);
}
// set lights separate for area lights
@@ -761,7 +823,7 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
ICustomMaterialSystem &theMaterialSystem(m_RenderContext.GetCustomMaterialSystem());
SShaderGeneratorGeneratedShader &theShader(GetShaderForProgram(inProgram));
- theShader.m_ViewProjMatrix.Set(inModelViewProjection);
+ theShader.m_ModelViewProjMatrix.Set(inModelViewProjection);
theShader.m_NormalMatrix.Set(inNormalMatrix);
theShader.m_ModelMatrix.Set(inGlobalTransform);
@@ -1065,7 +1127,9 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
IDefaultMaterialVertexPipeline &vertexShader(VertexGenerator());
IShaderStageGenerator &fragmentShader(FragmentGenerator());
- eastl::string srcString(theShaderBuffer.c_str());
+ QString str = QString::fromLatin1(theShaderBuffer.c_str());
+ insertSnapperDirectives(str);
+ eastl::string srcString(str.toLatin1().constData());
if (m_RenderContext.GetRenderContext().GetRenderContextType()
== NVRenderContextValues::GLES2) {
@@ -1239,12 +1303,14 @@ struct SShaderGenerator : public ICustomMaterialShaderGenerator
SShaderGeneratorGeneratedShader &shader(GetShaderForProgram(*program));
shader.m_ModelMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("modelMatrix",
*program);
- shader.m_ViewProjMatrix = NVRenderCachedShaderProperty<QT3DSMat44>(
+ shader.m_ModelViewProjMatrix = NVRenderCachedShaderProperty<QT3DSMat44>(
"modelViewProjection", *program);
shader.m_ViewMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("viewMatrix", *program);
shader.m_NormalMatrix = NVRenderCachedShaderProperty<QT3DSMat33>("modelNormalMatrix",
*program);
- shader.m_ProjMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("viewProjectionMatrix",
+ shader.m_ProjMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("projectionMatrix",
+ *program);
+ shader.m_ViewProjMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("viewProjectionMatrix",
*program);
shader.m_ViewportMatrix = NVRenderCachedShaderProperty<QT3DSMat44>("viewportMatrix",
*program);
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
index b40e10e..4e109dd 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.cpp
@@ -687,11 +687,12 @@ struct SCustomMaterialShader
{
NVScopedRefCounted<NVRenderShaderProgram> m_Shader;
NVRenderCachedShaderProperty<QT3DSMat44> m_ModelMatrix;
- NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ModelViewProjMatrix;
NVRenderCachedShaderProperty<QT3DSMat44> m_ViewMatrix;
NVRenderCachedShaderProperty<QT3DSMat33> m_NormalMatrix;
NVRenderCachedShaderProperty<QT3DSVec3> m_CameraPos;
NVRenderCachedShaderProperty<QT3DSMat44> m_ProjMatrix;
+ NVRenderCachedShaderProperty<QT3DSMat44> m_ViewProjMatrix;
NVRenderCachedShaderProperty<QT3DSMat44> m_ViewportMatrix;
NVRenderCachedShaderProperty<QT3DSVec2> m_CamProperties;
NVRenderCachedShaderProperty<NVRenderTexture2D *> m_DepthTexture;
@@ -712,11 +713,12 @@ struct SCustomMaterialShader
SCustomMaterialShader(NVRenderShaderProgram &inShader, SDynamicShaderProgramFlags inFlags)
: m_Shader(inShader)
, m_ModelMatrix("model_matrix", inShader)
- , m_ViewProjMatrix("model_view_projection", inShader)
+ , m_ModelViewProjMatrix("model_view_projection", inShader)
, m_ViewMatrix("view_matrix", inShader)
, m_NormalMatrix("normal_matrix", inShader)
, m_CameraPos("camera_position", inShader)
- , m_ProjMatrix("view_projection_matrix", inShader)
+ , m_ProjMatrix("projection_matrix", inShader)
+ , m_ViewProjMatrix("view_projection_matrix", inShader)
, m_ViewportMatrix("viewport_matrix", inShader)
, m_CamProperties("camera_properties", inShader)
, m_DepthTexture("depth_sampler", inShader)
@@ -873,8 +875,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
TShaderMap m_ShaderMap;
nvvector<TCustomMaterialTextureEntry> m_TextureEntries;
nvvector<SCustomMaterialBuffer> m_AllocatedBuffers;
- nvvector<TAllocatedImageEntry> m_AllocatedImages;
- nvvector<SCustomMaterial::TImageMapHash *> m_materialImageMaps;
bool m_UseFastBlits;
eastl::string m_ShaderNameBuilder;
QT3DSU64 m_LastFrameTime;
@@ -889,8 +889,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
, m_ShaderMap(ct.GetAllocator(), "SMaterialSystem::m_ShaderMap")
, m_TextureEntries(ct.GetAllocator(), "SMaterialSystem::m_TextureEntries")
, m_AllocatedBuffers(ct.GetAllocator(), "SMaterialSystem::m_AllocatedBuffers")
- , m_AllocatedImages(ct.GetAllocator(), "SMaterialSystem::m_AllocatedImages")
- , m_materialImageMaps(ct.GetAllocator(), "SMaterialSystem::m_materialImageMaps")
, m_UseFastBlits(true)
, m_LastFrameTime(0)
, m_MillisecondsSinceLastFrame(0)
@@ -911,22 +909,10 @@ struct SMaterialSystem : public ICustomMaterialSystem
void clearImageAndBufferCaches()
{
while (m_AllocatedBuffers.size())
- ReleaseBuffer(0);
-
- for (QT3DSU32 idx = 0; idx < m_AllocatedImages.size(); ++idx) {
- SImage *pImage = m_AllocatedImages[idx].second;
- QT3DS_FREE(m_CoreContext.GetAllocator(), pImage);
- }
- for (QT3DSU32 idx = 0; idx < m_materialImageMaps.size(); ++idx) {
- auto *matmap = m_materialImageMaps[idx];
- matmap->~nvhash_map();
- QT3DS_FREE(m_CoreContext.GetAllocator(), matmap);
- }
- m_materialImageMaps.clear();
- m_AllocatedImages.clear();
+ ReleaseBuffer(0, true);
}
- void ReleaseBuffer(QT3DSU32 inIdx)
+ void ReleaseBuffer(QT3DSU32 inIdx, bool forceRelease)
{
// Don't call this on MaterialSystem destroy.
// This causes issues for scene liftime buffers
@@ -936,8 +922,8 @@ struct SMaterialSystem : public ICustomMaterialSystem
theEntry.m_FrameBuffer->Attach(NVRenderFrameBufferAttachments::Color0,
NVRenderTextureOrRenderBuffer());
- theManager.Release(*theEntry.m_FrameBuffer);
- theManager.Release(*theEntry.m_Texture);
+ theManager.Release(*theEntry.m_FrameBuffer, forceRelease);
+ theManager.Release(*theEntry.m_Texture, forceRelease);
m_AllocatedBuffers.replace_with_last(inIdx);
}
@@ -954,7 +940,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
if (IsMaterialRegistered(inName))
return false;
m_CoreContext.GetDynamicObjectSystemCore().Register(
- inName, inProperties, sizeof(SCustomMaterial), GraphObjectTypes::CustomMaterial);
+ inName, inProperties, GraphObjectTypes::CustomMaterial);
IDynamicObjectClass *theClass =
m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
if (theClass == NULL) {
@@ -1012,14 +998,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
return m_AllocatedBuffers.size();
}
- virtual QT3DSU32 FindAllocatedImage(CRegisteredString inName)
- {
- for (QT3DSU32 idx = 0, end = m_AllocatedImages.size(); idx < end; ++idx)
- if (m_AllocatedImages[idx].first == inName)
- return idx;
- return QT3DSU32(-1);
- }
-
virtual bool TextureNeedsMips(const SPropertyDefinition *inPropDec,
qt3ds::render::NVRenderTexture2D *inTexture)
{
@@ -1101,7 +1079,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
SCustomMaterial *CreateCustomMaterial(CRegisteredString inName,
NVAllocatorCallback &inSceneGraphAllocator) override
{
- SCustomMaterial *theMaterial = static_cast<SCustomMaterial *>(
+ SCustomMaterial *theMaterial = QT3DS_NEW(inSceneGraphAllocator, SCustomMaterial)(
m_CoreContext.GetDynamicObjectSystemCore().CreateInstance(inName,
inSceneGraphAllocator));
SMaterialClass *theClass = GetMaterialClass(inName);
@@ -1264,6 +1242,9 @@ struct SMaterialSystem : public ICustomMaterialSystem
if (theProgram) {
theInsertResult.first->second =
QT3DS_NEW(m_Allocator, SCustomMaterialShader)(*theProgram, theFlags);
+ } else {
+ // If a changed shader fails to compile, clean away the old result from cache
+ theInsertResult.first->second = NULL;
}
} else if (theInsertResult.first->second)
theProgram = theInsertResult.first->second->m_Shader;
@@ -1292,6 +1273,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
NVRenderShaderProgram &inShader,
const SPropertyDefinition &inDefinition)
{
+ IStringTable &strTable = m_CoreContext.GetStringTable();
qt3ds::render::NVRenderShaderConstantBase *theConstant =
inShader.GetShaderConstant(inPropertyName);
using namespace qt3ds::render;
@@ -1301,24 +1283,42 @@ struct SMaterialSystem : public ICustomMaterialSystem
StaticAssert<sizeof(CRegisteredString)
== sizeof(NVRenderTexture2DPtr)>::valid_expression();
CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(inDataPtr);
- if (theStrPtr->IsValid() && inMaterial.m_imageMaps) {
- SImage *image = (*inMaterial.m_imageMaps)[inPropertyName];
- if (image) {
- if (image->m_ImagePath != *theStrPtr) {
- image->m_ImagePath = *theStrPtr;
- image->m_Flags.SetDirty(true);
- } else {
- if (image->m_OffscreenRendererId.IsValid()) {
- SetSubpresentation(inShader, inPropertyName,
- image->m_TextureData.m_Texture,
- &inDefinition);
- } else {
- SetTexture(inShader, inPropertyName,
- image->m_TextureData.m_Texture, &inDefinition,
- TextureNeedsMips(&inDefinition,
- image->m_TextureData.m_Texture));
- }
+
+ SImage *image = inMaterial.getImage(*theStrPtr);
+ if (image) {
+ CRegisteredString strU = strTable.RegisterStr(
+ QString::fromLatin1(inPropertyName.c_str()) + "TransformU");
+ CRegisteredString strV = strTable.RegisterStr(
+ QString::fromLatin1(inPropertyName.c_str()) + "TransformV");
+ qt3ds::render::NVRenderShaderConstantBase *transformU =
+ inShader.GetShaderConstant(strU);
+ qt3ds::render::NVRenderShaderConstantBase *transformV =
+ inShader.GetShaderConstant(strV);
+ image->CalculateTextureTransform();
+ QT3DSMat44 textureTransform = image->m_TextureTransform;
+ if (image->m_TextureData.m_TextureFlags.IsInvertUVCoords()) {
+ QT3DSMat44 invertCoordsMat(QT3DSMat44::createIdentity());
+ invertCoordsMat.scale(QT3DSVec4(1.0f, -1.0f, 1.0f, 1.0f));
+ invertCoordsMat.setPosition(QT3DSVec3(0.0f, 1.0f, 0.0f));
+ textureTransform = textureTransform * invertCoordsMat;
+ }
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ inShader.SetPropertyValue(transformU,
+ QT3DSVec3(dataPtr[0], dataPtr[4], dataPtr[12]));
+ inShader.SetPropertyValue(transformV,
+ QT3DSVec3(dataPtr[1], dataPtr[5], dataPtr[13]));
+ if (image->m_TextureData.m_Texture) {
+ auto *texture = image->m_TextureData.m_Texture;
+ texture->SetTextureWrapS(image->m_HorizontalTilingMode);
+ texture->SetTextureWrapT(image->m_VerticalTilingMode);
+ texture->SetMinFilter(image->m_MinFilter);
+ texture->SetMagFilter(image->m_MagFilter);
+ if (inDefinition.m_MinFilterOp != NVRenderTextureMinifyingOp::Nearest
+ && inDefinition.m_MinFilterOp != NVRenderTextureMinifyingOp::Linear
+ && !texture->GetNumMipmaps()) {
+ texture->GenerateMipmaps();
}
+ inShader.SetPropertyValue(theConstant, texture);
}
}
} else {
@@ -1348,15 +1348,16 @@ struct SMaterialSystem : public ICustomMaterialSystem
NVRenderShaderProgram &inShader, const SApplyInstanceValue &inCommand)
{
// sanity check
+ SDynamicObject &dynObj = *inMaterial.m_dynamicObject;
if (inCommand.m_PropertyName.IsValid()) {
bool canGetData =
inCommand.m_ValueOffset + getSizeofShaderDataType(inCommand.m_ValueType)
- <= inMaterial.m_DataSectionByteSize;
+ <= dynObj.m_DataSectionByteSize;
if (canGetData == false) {
QT3DS_ASSERT(false);
return;
}
- QT3DSU8 *dataPtr = inMaterial.GetDataSectionBegin() + inCommand.m_ValueOffset;
+ QT3DSU8 *dataPtr = dynObj.GetDataSectionOffset(inCommand.m_ValueOffset);
const SPropertyDefinition *theDefinition =
inClass.m_Class->FindPropertyByName(inCommand.m_PropertyName);
if (theDefinition)
@@ -1372,13 +1373,20 @@ struct SMaterialSystem : public ICustomMaterialSystem
// This is fine, the property wasn't found and we continue, no problem.
if (!theConstant)
continue;
- QT3DSU8 *dataPtr = inMaterial.GetDataSectionBegin() + theDefinition.m_Offset;
+ QT3DSU8 *dataPtr = dynObj.GetDataSectionOffset(theDefinition.m_Offset);
DoApplyInstanceValue(inMaterial, dataPtr, theDefinition.m_Name,
theDefinition.m_DataType, inShader, theDefinition);
}
}
}
+ void ApplyDepth(const SApplyDepth &inCommand)
+ {
+ NVRenderContext &theContext(m_Context->GetRenderContext());
+ theContext.SetDepthFunction(inCommand.m_depthFunc);
+ theContext.SetDepthWriteEnabled(inCommand.m_depthMask);
+ }
+
void ApplyBlending(const SApplyBlending &inCommand)
{
NVRenderContext &theContext(m_Context->GetRenderContext());
@@ -1397,6 +1405,31 @@ struct SMaterialSystem : public ICustomMaterialSystem
theContext.SetBlendEquation(blendEqu);
}
+ void ApplyRenderState(const SApplyRenderState &inCommand)
+ {
+ NVRenderContext &theContext(m_Context->GetRenderContext());
+
+ switch (inCommand.m_RenderState) {
+ case NVRenderState::CullFace:
+ theContext.SetCullingEnabled(inCommand.m_Enabled);
+ break;
+ case NVRenderState::StencilTest:
+ theContext.SetStencilTestEnabled(inCommand.m_Enabled);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void ApplyCulling(const SApplyCulling &inCommand)
+ {
+ NVRenderContext &theContext(m_Context->GetRenderContext());
+
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> state =
+ theContext.CreateRasterizerState(0.0, 0.0, inCommand.m_CullMode);
+ theContext.SetRasterizerState(state);
+ }
+
// we currently only bind a source texture
const NVRenderTexture2D *ApplyBufferValue(const SCustomMaterial &inMaterial,
NVRenderShaderProgram &inShader,
@@ -1480,7 +1513,7 @@ struct SMaterialSystem : public ICustomMaterialSystem
&& theDetails.m_Format == theFormat) {
theTexture = theEntry.m_Texture;
} else {
- ReleaseBuffer(bufferIdx);
+ ReleaseBuffer(bufferIdx, false);
}
}
@@ -1735,7 +1768,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
theContext.SetInputAssembler(&inAssembler);
- theContext.SetCullingEnabled(true);
QT3DSU32 count = inCount;
QT3DSU32 offset = inOffset;
@@ -1756,8 +1788,10 @@ struct SMaterialSystem : public ICustomMaterialSystem
// for refrative materials we come from the transparent render path
// but we do not want to do blending
bool wasBlendingEnabled = theContext.IsBlendingEnabled();
+ bool wasStencilEnabled = theContext.IsStencilTestEnabled();
if (inMaterial.m_hasRefraction)
theContext.SetBlendingEnabled(false);
+ theContext.SetCullingEnabled(true);
NVRenderContextScopedProperty<NVRenderFrameBuffer *> __framebuffer(
theContext, &NVRenderContext::GetRenderTarget, &NVRenderContext::SetRenderTarget);
@@ -1810,9 +1844,18 @@ struct SMaterialSystem : public ICustomMaterialSystem
// reset
theRenderTargetNeedsClear = false;
break;
+ case CommandTypes::ApplyCulling:
+ ApplyCulling(static_cast<const SApplyCulling &>(theCommand));
+ break;
+ case CommandTypes::ApplyRenderState:
+ ApplyRenderState(static_cast<const SApplyRenderState &>(theCommand));
+ break;
case CommandTypes::ApplyBlending:
ApplyBlending(static_cast<const SApplyBlending &>(theCommand));
break;
+ case CommandTypes::ApplyDepth:
+ ApplyDepth(static_cast<const SApplyDepth &>(theCommand));
+ break;
case CommandTypes::ApplyBufferValue:
if (theCurrentShader)
ApplyBufferValue(inMaterial, *theCurrentShader->m_Shader,
@@ -1831,11 +1874,18 @@ struct SMaterialSystem : public ICustomMaterialSystem
if (inMaterial.m_hasRefraction)
theContext.SetBlendingEnabled(wasBlendingEnabled);
+ theContext.SetStencilTestEnabled(wasStencilEnabled);
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> state =
+ theContext.CreateRasterizerState(0.0, 0.0, qt3ds::render::NVRenderFaces::Back);
+ theContext.SetRasterizerState(state);
+ theContext.SetCullingEnabled(true);
+ theContext.SetDepthFunction(NVRenderBoolOp::LessThanOrEqual);
+ theContext.SetDepthWriteEnabled(true);
// Release any per-frame buffers
for (QT3DSU32 idx = 0; idx < m_AllocatedBuffers.size(); ++idx) {
if (m_AllocatedBuffers[idx].m_Flags.IsSceneLifetime() == false) {
- ReleaseBuffer(idx);
+ ReleaseBuffer(idx, false);
--idx;
}
}
@@ -1874,17 +1924,18 @@ struct SMaterialSystem : public ICustomMaterialSystem
applier);
}
- void renderSubpresentations(SCustomMaterial &inMaterial) override
+ bool renderSubpresentations(SCustomMaterial &inMaterial) override
{
SMaterialClass *theClass = GetMaterialClass(inMaterial.m_ClassName);
if (!theClass)
- return;
+ return false;
+ bool wasDirty = false;
NVConstDataRef<SPropertyDefinition> theDefs = theClass->m_Class->GetProperties();
for (QT3DSU32 idx = 0, end = theDefs.size(); idx < end; ++idx) {
const SPropertyDefinition &theDefinition(theDefs[idx]);
if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
- QT3DSU8 *dataPtr = inMaterial.GetDataSectionBegin() + theDefinition.m_Offset;
+ QT3DSU8 *dataPtr = inMaterial.m_dynamicObject->GetDataSectionOffset(theDefinition.m_Offset);
StaticAssert<sizeof(CRegisteredString)
== sizeof(NVRenderTexture2DPtr)>::valid_expression();
CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(dataPtr);
@@ -1892,11 +1943,16 @@ struct SMaterialSystem : public ICustomMaterialSystem
m_Context->GetOffscreenRenderManager());
if (theStrPtr->IsValid()) {
- if (theOffscreenRenderer.HasOffscreenRenderer(*theStrPtr))
- theOffscreenRenderer.GetRenderedItem(*theStrPtr);
+ if (theOffscreenRenderer.HasOffscreenRenderer(*theStrPtr)) {
+ SOffscreenRenderResult result
+ = theOffscreenRenderer.GetRenderedItem(*theStrPtr);
+ if (result.m_HasChangedSinceLastFrame)
+ wasDirty = true;
+ }
}
}
}
+ return wasDirty;
}
void clearCaches() override
@@ -1929,91 +1985,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
return theClass->m_Class->RequiresCompilation();
}
- SCustomMaterial::TImageMapHash *newImageMap(NVAllocatorCallback &allocator)
- {
- const char *name = "SCustomMaterial::TImageMapHash";
- SCustomMaterial::TImageMapHash *ret
- = new (QT3DS_ALLOC(allocator, sizeof(SCustomMaterial::TImageMapHash), name))
- SCustomMaterial::TImageMapHash(allocator, name);
- m_materialImageMaps.push_back(ret);
- return ret;
- }
-
- virtual void PrepareTextureForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
- {
- NVConstDataRef<SPropertyDefinition> thePropDefs = inClass.m_Class->GetProperties();
- for (QT3DSU32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) {
- if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
- SImage *pImage = nullptr;
- CRegisteredString theStrPtr = *reinterpret_cast<CRegisteredString *>(
- inMaterial.GetDataSectionBegin() + thePropDefs[idx].m_Offset);
-
- if (theStrPtr.IsValid()) {
- QT3DSU32 index = FindAllocatedImage(theStrPtr);
- if (index == QT3DSU32(-1)) {
- pImage = QT3DS_NEW(m_CoreContext.GetAllocator(), SImage)();
- m_AllocatedImages.push_back(eastl::make_pair(theStrPtr, pImage));
- } else {
- pImage = m_AllocatedImages[index].second;
- }
-
- switch (thePropDefs[idx].m_TexUsageType) {
- case NVRenderTextureTypeValue::Displace:
- if (inMaterial.m_DisplacementMap != pImage) {
- inMaterial.m_DisplacementMap = pImage;
- inMaterial.m_DisplacementMap->m_ImagePath =
- thePropDefs[idx].m_ImagePath;
- inMaterial.m_DisplacementMap->m_ImageShaderName =
- thePropDefs[idx].m_Name; // this is our name in the shader
- inMaterial.m_DisplacementMap->m_VerticalTilingMode =
- thePropDefs[idx].m_CoordOp;
- inMaterial.m_DisplacementMap->m_HorizontalTilingMode =
- thePropDefs[idx].m_CoordOp;
- }
- break;
- case NVRenderTextureTypeValue::Emissive2:
- if (inMaterial.m_EmissiveMap2 != pImage) {
- inMaterial.m_EmissiveMap2 = pImage;
- inMaterial.m_EmissiveMap2->m_ImagePath = thePropDefs[idx].m_ImagePath;
- inMaterial.m_EmissiveMap2->m_ImageShaderName =
- thePropDefs[idx].m_Name; // this is our name in the shader
- inMaterial.m_EmissiveMap2->m_VerticalTilingMode =
- thePropDefs[idx].m_CoordOp;
- inMaterial.m_EmissiveMap2->m_HorizontalTilingMode =
- thePropDefs[idx].m_CoordOp;
- }
- break;
- default:
- if (!inMaterial.m_imageMaps)
- inMaterial.m_imageMaps = newImageMap(m_CoreContext.GetAllocator());
- if ((*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] != pImage) {
- (*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] = pImage;
- pImage->m_ImagePath = thePropDefs[idx].m_ImagePath;
- pImage->m_ImageShaderName = thePropDefs[idx].m_Name;
- pImage->m_VerticalTilingMode = thePropDefs[idx].m_CoordOp;
- pImage->m_HorizontalTilingMode = thePropDefs[idx].m_CoordOp;
- }
- break;
- }
- } else {
- switch (thePropDefs[idx].m_TexUsageType) {
- case NVRenderTextureTypeValue::Displace:
- inMaterial.m_DisplacementMap = nullptr;
- break;
- case NVRenderTextureTypeValue::Emissive2:
- inMaterial.m_EmissiveMap2 = nullptr;
- break;
- default:
- if (!inMaterial.m_imageMaps)
- inMaterial.m_imageMaps = newImageMap(m_CoreContext.GetAllocator());
- (*inMaterial.m_imageMaps)[thePropDefs[idx].m_Name] = nullptr;
- break;
- }
- }
- }
- }
- }
-
virtual void PrepareDisplacementForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
{
if (inMaterial.m_DisplacementMap == NULL)
@@ -2024,13 +1995,11 @@ struct SMaterialSystem : public ICustomMaterialSystem
for (QT3DSU32 idx = 0, end = thePropDefs.size(); idx < end; ++idx) {
if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::QT3DSF32
&& AreEqual(thePropDefs[idx].m_Name.c_str(), "displaceAmount")) {
- QT3DSF32 theValue = *reinterpret_cast<const QT3DSF32 *>(inMaterial.GetDataSectionBegin()
- + thePropDefs[idx].m_Offset);
+ QT3DSF32 theValue = *reinterpret_cast<const QT3DSF32 *>(inMaterial.m_dynamicObject->GetDataSectionOffset(thePropDefs[idx].m_Offset));
inMaterial.m_DisplaceAmount = theValue;
} else if (thePropDefs[idx].m_DataType == NVRenderShaderDataTypes::QT3DSVec3
&& AreEqual(thePropDefs[idx].m_Name.c_str(), "displace_tiling")) {
- QT3DSVec3 theValue = *reinterpret_cast<const QT3DSVec3 *>(inMaterial.GetDataSectionBegin()
- + thePropDefs[idx].m_Offset);
+ QT3DSVec3 theValue = *reinterpret_cast<const QT3DSVec3 *>(inMaterial.m_dynamicObject->GetDataSectionOffset(thePropDefs[idx].m_Offset));
if (theValue.x != inMaterial.m_DisplacementMap->m_Scale.x
|| theValue.y != inMaterial.m_DisplacementMap->m_Scale.y) {
inMaterial.m_DisplacementMap->m_Scale = QT3DSVec2(theValue.x, theValue.y);
@@ -2042,8 +2011,6 @@ struct SMaterialSystem : public ICustomMaterialSystem
void PrepareMaterialForRender(SMaterialClass &inClass, SCustomMaterial &inMaterial)
{
- PrepareTextureForRender(inClass, inMaterial);
-
if (inClass.m_HasDisplacement)
PrepareDisplacementForRender(inClass, inMaterial);
}
diff --git a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h
index 0f87533..9a46554 100644
--- a/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h
+++ b/src/runtimerender/Qt3DSRenderCustomMaterialSystem.h
@@ -127,7 +127,7 @@ namespace render {
// apply property values
virtual void ApplyShaderPropertyValues(const SCustomMaterial &inMaterial,
NVRenderShaderProgram &inProgram) = 0;
- virtual void renderSubpresentations(SCustomMaterial &inMaterial) = 0;
+ virtual bool renderSubpresentations(SCustomMaterial &inMaterial) = 0;
virtual void clearCaches() = 0;
virtual void setRequiresCompilation(const CRegisteredString &name, bool value) = 0;
virtual bool requiresCompilation(const CRegisteredString &name) const = 0;
diff --git a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
index 0789d51..cfa6cff 100644
--- a/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
+++ b/src/runtimerender/Qt3DSRenderDefaultMaterialShaderGenerator.cpp
@@ -395,7 +395,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
void AddLocalVariable(IShaderStageGenerator &inGenerator, const char8_t *inName,
const char8_t *inType)
{
- inGenerator << "\t" << inType << " " << inName << ";" << Endl;
+ inGenerator << " " << inType << " " << inName << ";" << Endl;
}
void AddLocalVariable(IShaderStageGenerator &inGenerator, const TStrType &inName,
@@ -414,41 +414,44 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
SetupTexCoordVariableName(uvSet);
fragmentShader.AddUniform(m_ImageSampler, "sampler2D");
vertexShader.AddUniform(m_ImageOffsets, "vec3");
- fragmentShader.AddUniform(m_ImageOffsets, "vec3");
vertexShader.AddUniform(m_ImageRotations, "vec4");
- fragmentShader.AddUniform(m_ImageRotations, "vec4");
if (image.m_Image.m_MappingMode == ImageMappingModes::Normal) {
- vertexShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, "
+ vertexShader << " uTransform = vec3( " << m_ImageRotations << ".x, "
<< m_ImageRotations << ".y, " << m_ImageOffsets << ".x );" << Endl;
- vertexShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, "
+ vertexShader << " vTransform = vec3( " << m_ImageRotations << ".z, "
<< m_ImageRotations << ".w, " << m_ImageOffsets << ".y );" << Endl;
vertexShader.AddOutgoing(m_ImageFragCoords, "vec2");
addFunction(vertexShader, "getTransformedUVCoords");
vertexShader.GenerateUVCoords(uvSet);
m_ImageTemp = m_ImageFragCoords;
m_ImageTemp.append("temp");
- vertexShader << "\tvec2 " << m_ImageTemp << " = getTransformedUVCoords( vec3( "
+ vertexShader << " vec2 " << m_ImageTemp << " = getTransformedUVCoords( vec3( "
<< m_TexCoordTemp << ", 1.0), uTransform, vTransform );" << Endl;
- if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
- vertexShader << "\t" << m_ImageTemp << ".y = 1.0 - " << m_ImageFragCoords << ".y;"
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords()) {
+ vertexShader << " " << m_ImageTemp << ".y = 1.0 - " << m_ImageTemp << ".y;"
<< Endl;
+ }
vertexShader.AssignOutput(m_ImageFragCoords.c_str(), m_ImageTemp.c_str());
} else {
- fragmentShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, "
+ fragmentShader.AddUniform(m_ImageOffsets, "vec3");
+ fragmentShader.AddUniform(m_ImageRotations, "vec4");
+ fragmentShader << " uTransform = vec3( " << m_ImageRotations << ".x, "
<< m_ImageRotations << ".y, " << m_ImageOffsets << ".x );" << Endl;
- fragmentShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, "
+ fragmentShader << " vTransform = vec3( " << m_ImageRotations << ".z, "
<< m_ImageRotations << ".w, " << m_ImageOffsets << ".y );" << Endl;
vertexShader.GenerateEnvMapReflection();
addFunction(fragmentShader, "getTransformedUVCoords");
- fragmentShader << "\tvec2 " << m_ImageFragCoords
+ fragmentShader << " vec2 " << m_ImageFragCoords
<< " = getTransformedUVCoords( environment_map_reflection, uTransform, "
"vTransform );"
<< Endl;
- if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
- fragmentShader << "\t" << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords
+
+ if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords()) {
+ fragmentShader << " " << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords
<< ".y;" << Endl;
+ }
}
}
@@ -466,19 +469,19 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
inShader.AddUniform(m_ImageOffsets, "vec3");
inShader.AddUniform(m_ImageRotations, "vec4");
- inShader << "\tuTransform = vec3( " << m_ImageRotations << ".x, " << m_ImageRotations
+ inShader << " uTransform = vec3( " << m_ImageRotations << ".x, " << m_ImageRotations
<< ".y, " << m_ImageOffsets << ".x );" << Endl;
- inShader << "\tvTransform = vec3( " << m_ImageRotations << ".z, " << m_ImageRotations
+ inShader << " vTransform = vec3( " << m_ImageRotations << ".z, " << m_ImageRotations
<< ".w, " << m_ImageOffsets << ".y );" << Endl;
- inShader << "\tvec2 " << m_ImageFragCoords << ";" << Endl;
+ inShader << " vec2 " << m_ImageFragCoords << ";" << Endl;
addFunction(inShader, "getTransformedUVCoords");
inShader.GenerateUVCoords();
inShader
- << "\t" << m_ImageFragCoords
+ << " " << m_ImageFragCoords
<< " = getTransformedUVCoords( vec3( varTexCoord0, 1.0), uTransform, vTransform );"
<< Endl;
if (image.m_Image.m_TextureData.m_TextureFlags.IsInvertUVCoords())
- inShader << "\t" << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords << ".y;"
+ inShader << " " << m_ImageFragCoords << ".y = 1.0 - " << m_ImageFragCoords << ".y;"
<< Endl;
}
}
@@ -491,7 +494,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
case DefaultMaterialSpecularModel::KGGX: {
fragmentShader.AddInclude("defaultMaterialPhysGlossyBSDF.glsllib");
fragmentShader.AddUniform("material_specular", "vec4");
- fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ fragmentShader << " global_specular_light.rgb += lightAttenuation * specularAmount * "
"specularColor * kggxGlossyDefaultMtl( "
<< "world_normal, tangent, -" << inLightDir << ".xyz, view_vector, "
<< inLightSpecColor
@@ -502,7 +505,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
case DefaultMaterialSpecularModel::KWard: {
fragmentShader.AddInclude("defaultMaterialPhysGlossyBSDF.glsllib");
fragmentShader.AddUniform("material_specular", "vec4");
- fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ fragmentShader << " global_specular_light.rgb += lightAttenuation * specularAmount * "
"specularColor * wardGlossyDefaultMtl( "
<< "world_normal, tangent, -" << inLightDir << ".xyz, view_vector, "
<< inLightSpecColor
@@ -512,11 +515,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
} break;
default:
addFunction(fragmentShader, "specularBSDF");
- fragmentShader << "\tglobal_specular_light.rgb += lightAttenuation * specularAmount * "
+ fragmentShader << " global_specular_light.rgb += lightAttenuation * specularAmount * "
"specularColor * specularBSDF( "
<< "world_normal, -" << inLightDir << ".xyz, view_vector, "
- << inLightSpecColor << ".rgb, 1.0, 2.56 / (roughnessAmount + "
- "0.01), vec3(1.0), scatter_reflect ).rgb;"
+ << inLightSpecColor << ".rgb, 2.56 / (roughnessAmount + "
+ "0.01)).rgb;"
<< Endl;
break;
}
@@ -527,7 +530,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
{
m_NormalizedDirection = inLightPrefix + "_areaDir";
AddLocalVariable(infragmentShader, m_NormalizedDirection, "vec3");
- infragmentShader << "\tlightAttenuation = calculateDiffuseAreaOld( " << m_LightDirection
+ infragmentShader << " lightAttenuation = calculateDiffuseAreaOld( " << m_LightDirection
<< ".xyz, " << m_LightPos << ".xyz, " << m_LightUp << ", " << m_LightRt
<< ", " << inPos << ", " << m_NormalizedDirection << " );" << Endl;
}
@@ -542,7 +545,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
"specularAmount * sampleAreaGlossyDefault( tanFrame, "
<< inPos << ", " << m_NormalizedDirection << ", " << m_LightPos << ".xyz, "
<< m_LightRt << ".w, " << m_LightUp << ".w, " << inView
- << ", roughnessAmount, roughnessAmount ).rgb;" << Endl;
+ << ", roughnessAmount).rgb;" << Endl;
}
void AddTranslucencyIrradiance(IShaderStageGenerator &infragmentShader, SRenderableImage *image,
@@ -553,13 +556,13 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
addFunction(infragmentShader, "diffuseReflectionWrapBSDF");
if (areaLight) {
- infragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ infragmentShader << " global_diffuse_light.rgb += lightAttenuation * "
"translucent_thickness_exp * diffuseReflectionWrapBSDF( "
"-world_normal, "
<< m_NormalizedDirection << ", " << m_LightColor
<< ".rgb, diffuseLightWrap ).rgb;" << Endl;
} else {
- infragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ infragmentShader << " global_diffuse_light.rgb += lightAttenuation * "
"translucent_thickness_exp * diffuseReflectionWrapBSDF( "
"-world_normal, "
<< "-" << m_NormalizedDirection << ", " << m_LightColor
@@ -601,7 +604,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if ( inType == RenderLightTypes::Area )
{
inLightShader << "vec2 " << m_ShadowCoordStem << ";" << Endl;
- inLightShader << "\tshadow_map_occl = sampleParaboloid( " << m_ShadowMapStem << ", "
+ inLightShader << " shadow_map_occl = sampleParaboloid( " << m_ShadowMapStem << ", "
<< m_ShadowControlStem << ", "
<<
m_ShadowMatrixStem << ", varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z), "
@@ -610,12 +613,12 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
else */
if (inType != RenderLightTypes::Directional) {
- inLightShader << "\tshadow_map_occl = sampleCubemap( " << m_ShadowCubeStem << ", "
+ inLightShader << " shadow_map_occl = sampleCubemap( " << m_ShadowCubeStem << ", "
<< m_ShadowControlStem << ", " << m_ShadowMatrixStem << ", " << m_LightPos
<< ".xyz, varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z) );"
<< Endl;
} else
- inLightShader << "\tshadow_map_occl = sampleOrthographic( " << m_ShadowMapStem << ", "
+ inLightShader << " shadow_map_occl = sampleOrthographic( " << m_ShadowMapStem << ", "
<< m_ShadowControlStem << ", " << m_ShadowMatrixStem
<< ", varWorldPos, vec2(1.0, " << m_ShadowControlStem << ".z) );" << Endl;
}
@@ -630,18 +633,18 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
inShader.AddUniform("displacementMap_offset", "vec3");
inShader.AddInclude("defaultMaterialFileDisplacementTexture.glsllib");
- inShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
+ inShader.Append(" vec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
"displacementMap_offset.x );");
- inShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
+ inShader.Append(" vec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
"displacementMap_offset.y );");
addFunction(inShader, "getTransformedUVCoords");
- inShader.Append("\tvec2 uv_coords = attr_uv0;");
- inShader << "\tuv_coords = getTransformedUVCoords( vec3( uv_coords, 1.0), uTransform, "
+ inShader.Append(" vec2 uv_coords = attr_uv0;");
+ inShader << " uv_coords = getTransformedUVCoords( vec3( uv_coords, 1.0), uTransform, "
"vTransform );\n";
- inShader << "\tvec3 displacedPos = defaultMaterialFileDisplacementTexture( "
+ inShader << " vec3 displacedPos = defaultMaterialFileDisplacementTexture( "
"displacementSampler , displaceAmount, uv_coords , attr_norm, attr_pos );"
<< Endl;
- inShader.Append("\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ inShader.Append(" gl_Position = model_view_projection * vec4(displacedPos, 1.0);");
}
void AddDisplacementImageUniforms(IShaderStageGenerator &inGenerator,
@@ -663,15 +666,15 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
{
if (m_DefaultMaterialShaderKeyProperties.m_FresnelEnabled.GetValue(inKey)) {
if (inFragmentHasSpecularAmount == false)
- fragmentShader << "\tfloat specularAmount = 1.0;" << Endl;
+ fragmentShader << " float specularAmount = 1.0;" << Endl;
inFragmentHasSpecularAmount = true;
fragmentShader.AddInclude("defaultMaterialFresnel.glsllib");
fragmentShader.AddUniform("fresnelPower", "float");
fragmentShader.AddUniform("material_specular", "vec4");
- fragmentShader << "\tfloat fresnelRatio = defaultMaterialSimpleFresnel( world_normal, "
+ fragmentShader << " float fresnelRatio = defaultMaterialSimpleFresnel( world_normal, "
"view_vector, material_specular.w, fresnelPower );"
<< Endl;
- fragmentShader << "\tspecularAmount *= fresnelRatio;" << Endl;
+ fragmentShader << " specularAmount *= fresnelRatio;" << Endl;
}
return inFragmentHasSpecularAmount;
}
@@ -742,18 +745,18 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
inShader.AddUniform("displacementMap_offset", "vec3");
inShader.AddInclude("defaultMaterialFileDisplacementTexture.glsllib");
- inShader.Append("\tvec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
+ inShader.Append(" vec3 uTransform = vec3( displacementMap_rot.x, displacementMap_rot.y, "
"displacementMap_offset.x );");
- inShader.Append("\tvec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
+ inShader.Append(" vec3 vTransform = vec3( displacementMap_rot.z, displacementMap_rot.w, "
"displacementMap_offset.y );");
addFunction(inShader, "getTransformedUVCoords");
inShader.GenerateUVCoords();
- inShader << "\tvarTexCoord0 = getTransformedUVCoords( vec3( varTexCoord0, 1.0), "
+ inShader << " varTexCoord0 = getTransformedUVCoords( vec3( varTexCoord0, 1.0), "
"uTransform, vTransform );\n";
- inShader << "\tvec3 displacedPos = defaultMaterialFileDisplacementTexture( "
+ inShader << " vec3 displacedPos = defaultMaterialFileDisplacementTexture( "
"displacementSampler , displaceAmount, varTexCoord0 , attr_norm, attr_pos );"
<< Endl;
- inShader.Append("\tgl_Position = model_view_projection * vec4(displacedPos, 1.0);");
+ inShader.Append(" gl_Position = model_view_projection * vec4(displacedPos, 1.0);");
}
void GenerateTextureSwizzle(NVRenderTextureSwizzleMode::Enum swizzleMode,
@@ -859,6 +862,12 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
inImage.m_Image.m_HorizontalTilingMode);
inImage.m_Image.m_TextureData.m_Texture->SetTextureWrapT(
inImage.m_Image.m_VerticalTilingMode);
+ if (inImage.m_Image.m_MinFilter > NVRenderTextureMinifyingOp::Linear
+ && inImage.m_Image.m_TextureData.m_Texture->GetNumMipmaps() == 0) {
+ inImage.m_Image.m_TextureData.m_Texture->GenerateMipmaps();
+ }
+ inImage.m_Image.m_TextureData.m_Texture->SetMinFilter(inImage.m_Image.m_MinFilter);
+ inImage.m_Image.m_TextureData.m_Texture->SetMagFilter(inImage.m_Image.m_MagFilter);
theShaderProps.m_Sampler.Set(imageTexture);
theShaderProps.m_Offsets.Set(offsets);
theShaderProps.m_Rotations.Set(rotations);
@@ -875,14 +884,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
/*
VertexGenerator().AddUniform( m_ShadowMatrixStem, "mat4" );
VertexGenerator().AddOutgoing( m_ShadowCoordStem, "vec4" );
- VertexGenerator() << "\tvec4 local_" << m_ShadowCoordStem << " = " << m_ShadowMatrixStem
+ VertexGenerator() << " vec4 local_" << m_ShadowCoordStem << " = " << m_ShadowMatrixStem
<< " * vec4(local_model_world_position, 1.0);" << Endl;
m_TempStr.assign( "local_" );
m_TempStr.append( m_ShadowCoordStem );
VertexGenerator().AssignOutput( m_ShadowCoordStem.c_str(), m_TempStr.c_str() );
*/
} else {
- FragmentGenerator() << "\tshadow_map_occl = 1.0;" << Endl;
+ FragmentGenerator() << " shadow_map_occl = 1.0;" << Endl;
}
}
@@ -1035,9 +1044,9 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
// generated.
// we rely on the linker to strip out what isn't necessary instead of explicitly stripping
// it for code simplicity.
- if (hasImage) {
- fragmentShader.Append("\tvec3 uTransform;");
- fragmentShader.Append("\tvec3 vTransform;");
+ if (hasImage || hasLighting || hasLightmaps) {
+ fragmentShader.Append(" vec3 uTransform;");
+ fragmentShader.Append(" vec3 vTransform;");
}
if (includeSSAOSSDOVars || hasSpecMap || hasLighting || hasEnvMap || enableFresnel
@@ -1052,7 +1061,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if (vertexColorsEnabled)
vertexShader.GenerateVertexColor();
else
- fragmentShader.Append("\tvec3 vertColor = vec3(1.0);");
+ fragmentShader.Append(" vec3 vertColor = vec3(1.0);");
// You do bump or normal mapping but not both
if (bumpImage != nullptr) {
@@ -1061,41 +1070,41 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader.AddUniform(m_ImageSamplerSize, "vec2");
fragmentShader.AddInclude("defaultMaterialBumpNoLod.glsllib");
- fragmentShader << "\tworld_normal = defaultMaterialBumpNoLod( " << m_ImageSampler
+ fragmentShader << " world_normal = defaultMaterialBumpNoLod( " << m_ImageSampler
<< ", bumpAmount, " << m_ImageFragCoords
<< ", tangent, binormal, world_normal, "
<< m_ImageSamplerSize << ");" << Endl;
// Do gram schmidt
- fragmentShader << "\tbinormal = normalize(cross(world_normal, tangent) );\n";
- fragmentShader << "\ttangent = normalize(cross(binormal, world_normal) );\n";
+ fragmentShader << " binormal = normalize(cross(world_normal, tangent) );\n";
+ fragmentShader << " tangent = normalize(cross(binormal, world_normal) );\n";
} else if (normalImage != nullptr) {
GenerateImageUVCoordinates(normalImageIdx, *normalImage);
- fragmentShader.AddInclude("defaultMaterialFileNormalTexture.glsllib");
+ fragmentShader.AddFunction("sampleNormalTexture");
fragmentShader.AddUniform("bumpAmount", "float");
- fragmentShader << "\tworld_normal = defaultMaterialFileNormalTexture( "
+ fragmentShader << " world_normal = sampleNormalTexture( "
<< m_ImageSampler << ", bumpAmount, " << m_ImageFragCoords
- << ", tangent, binormal );" << Endl;
+ << ", tangent, binormal, world_normal);" << Endl;
}
if (includeSSAOSSDOVars || specularEnabled || hasIblProbe || enableBumpNormal)
- fragmentShader << "\tmat3 tanFrame = mat3(tangent, binormal, world_normal);" << Endl;
+ fragmentShader << " mat3 tanFrame = mat3(tangent, binormal, world_normal);" << Endl;
bool fragmentHasSpecularAmount = false;
if (hasEmissiveMap) {
- fragmentShader.Append("\tvec3 global_emission = material_diffuse.rgb;");
+ fragmentShader.Append(" vec3 global_emission = material_diffuse.rgb;");
}
if (hasLighting) {
fragmentShader.AddUniform("light_ambient_total", "vec3");
fragmentShader.Append(
- "\tvec4 global_diffuse_light = vec4(light_ambient_total.xyz, 1.0);");
- fragmentShader.Append("\tvec3 global_specular_light = vec3(0.0, 0.0, 0.0);");
- fragmentShader.Append("\tfloat shadow_map_occl = 1.0;");
+ " vec4 global_diffuse_light = vec4(light_ambient_total.xyz, 1.0);");
+ fragmentShader.Append(" vec3 global_specular_light = vec3(0.0, 0.0, 0.0);");
+ fragmentShader.Append(" float shadow_map_occl = 1.0;");
if (specularEnabled) {
vertexShader.GenerateViewVector();
@@ -1104,24 +1113,24 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if (lightmapIndirectImage != nullptr) {
GenerateImageUVCoordinates(lightmapIndirectImageIdx, *lightmapIndirectImage, 1);
- fragmentShader << "\tvec4 indirect_light = texture2D( " << m_ImageSampler << ", "
+ fragmentShader << " vec4 indirect_light = texture2D( " << m_ImageSampler << ", "
<< m_ImageFragCoords << ");" << Endl;
- fragmentShader << "\tglobal_diffuse_light += indirect_light;" << Endl;
+ fragmentShader << " global_diffuse_light += indirect_light;" << Endl;
if (specularEnabled) {
fragmentShader
- << "\tglobal_specular_light += indirect_light.rgb * material_properties.x;"
+ << " global_specular_light += indirect_light.rgb * material_properties.x;"
<< Endl;
}
}
if (lightmapRadiosityImage != nullptr) {
GenerateImageUVCoordinates(lightmapRadiosityImageIdx, *lightmapRadiosityImage, 1);
- fragmentShader << "\tvec4 direct_light = texture2D( " << m_ImageSampler << ", "
+ fragmentShader << " vec4 direct_light = texture2D( " << m_ImageSampler << ", "
<< m_ImageFragCoords << ");" << Endl;
- fragmentShader << "\tglobal_diffuse_light += direct_light;" << Endl;
+ fragmentShader << " global_diffuse_light += direct_light;" << Endl;
if (specularEnabled) {
fragmentShader
- << "\tglobal_specular_light += direct_light.rgb * material_properties.x;"
+ << " global_specular_light += direct_light.rgb * material_properties.x;"
<< Endl;
}
}
@@ -1132,52 +1141,52 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
GenerateImageUVCoordinates(translucencyImageIdx, *translucencyImage);
- fragmentShader << "\tvec4 translucent_depth_range = texture2D( " << m_ImageSampler
+ fragmentShader << " vec4 translucent_depth_range = texture2D( " << m_ImageSampler
<< ", " << m_ImageFragCoords << ");" << Endl;
- fragmentShader << "\tfloat translucent_thickness = translucent_depth_range.r * "
+ fragmentShader << " float translucent_thickness = translucent_depth_range.r * "
"translucent_depth_range.r;"
<< Endl;
- fragmentShader << "\tfloat translucent_thickness_exp = exp( translucent_thickness "
+ fragmentShader << " float translucent_thickness_exp = exp( translucent_thickness "
"* translucentFalloff);"
<< Endl;
}
- fragmentShader.Append("\tfloat lightAttenuation = 1.0;");
+ fragmentShader.Append(" float lightAttenuation = 1.0;");
AddLocalVariable(fragmentShader, "aoFactor", "float");
if (hasLighting && enableSSAO)
- fragmentShader.Append("\taoFactor = customMaterialAO();");
+ fragmentShader.Append(" aoFactor = customMaterialAO();");
else
- fragmentShader.Append("\taoFactor = 1.0;");
+ fragmentShader.Append(" aoFactor = 1.0;");
AddLocalVariable(fragmentShader, "shadowFac", "float");
if (specularEnabled) {
- fragmentShader << "\tfloat specularAmount = material_properties.x;" << Endl;
+ fragmentShader << " float specularAmount = material_properties.x;" << Endl;
fragmentHasSpecularAmount = true;
}
// Fragment lighting means we can perhaps attenuate the specular amount by a texture
// lookup.
- fragmentShader << "\tvec3 specularColor = vec3(1.0);" << Endl;
+ fragmentShader << " vec3 specularColor = vec3(1.0);" << Endl;
if (specularAmountImage) {
if (!specularEnabled)
- fragmentShader << "\tfloat specularAmount = 1.0;" << Endl;
+ fragmentShader << " float specularAmount = 1.0;" << Endl;
GenerateImageUVCoordinates(specularAmountImageIdx, *specularAmountImage);
- fragmentShader << "\tspecularColor = texture2D( "
+ fragmentShader << " specularColor = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << " ).xyz;" << Endl;
fragmentHasSpecularAmount = true;
}
- fragmentShader << "\tfloat roughnessAmount = material_properties.y;" << Endl;
+ fragmentShader << " float roughnessAmount = material_properties.y;" << Endl;
if (roughnessImage) {
GenerateImageUVCoordinates(roughnessImageIdx, *roughnessImage);
- fragmentShader << "\tfloat sampledRoughness = texture2D( "
+ fragmentShader << " float sampledRoughness = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << " ).x;" << Endl;
//The roughness sampled from roughness textures is Disney roughness
//which has to be squared to get the proper value
- fragmentShader << "\troughnessAmount = roughnessAmount * "
+ fragmentShader << " roughnessAmount = roughnessAmount * "
<< "sampledRoughness * sampledRoughness;" << Endl;
}
@@ -1199,8 +1208,8 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
m_TempStr.assign("light");
m_TempStr.append(buf);
- fragmentShader << "\t//Light " << buf << Endl;
- fragmentShader << "\tlightAttenuation = 1.0;" << Endl;
+ fragmentShader << " //Light " << buf << Endl;
+ fragmentShader << " lightAttenuation = 1.0;" << Endl;
if (isDirectional) {
if (m_LightsAsSeparateUniforms) {
@@ -1209,22 +1218,22 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
if (enableSSDO) {
- fragmentShader << "\tshadowFac = customMaterialShadow( " << m_LightDirection
+ fragmentShader << " shadowFac = customMaterialShadow( " << m_LightDirection
<< ".xyz, varWorldPos );" << Endl;
} else {
- fragmentShader << "\tshadowFac = 1.0;" << Endl;
+ fragmentShader << " shadowFac = 1.0;" << Endl;
}
GenerateShadowMapOcclusion(lightIdx, enableShadowMaps && isShadow,
lightNode->m_LightType);
if (specularEnabled && enableShadowMaps && isShadow)
- fragmentShader << "\tlightAttenuation *= shadow_map_occl;" << Endl;
+ fragmentShader << " lightAttenuation *= shadow_map_occl;" << Endl;
- fragmentShader << "\tglobal_diffuse_light.rgb += shadowFac * shadow_map_occl * "
+ fragmentShader << " global_diffuse_light.rgb += shadowFac * shadow_map_occl * "
"diffuseReflectionBSDF( world_normal, "
- << "-" << m_LightDirection << ".xyz, view_vector, "
- << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl;
+ << "-" << m_LightDirection << ".xyz, "
+ << m_LightColor << ".rgb).rgb;" << Endl;
if (specularEnabled) {
if (m_LightsAsSeparateUniforms)
@@ -1250,7 +1259,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
// Debug measure to make sure paraboloid sampling was projecting to the right
// location
- // fragmentShader << "\tglobal_diffuse_light.rg += " << m_ShadowCoordStem << ";"
+ // fragmentShader << " global_diffuse_light.rg += " << m_ShadowCoordStem << ";"
// << Endl;
m_NormalizedDirection = m_TempStr;
m_NormalizedDirection.append("_Frame");
@@ -1261,10 +1270,10 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
<< Endl;
if (enableSSDO) {
- fragmentShader << "\tshadowFac = shadow_map_occl * customMaterialShadow( "
+ fragmentShader << " shadowFac = shadow_map_occl * customMaterialShadow( "
<< m_LightDirection << ".xyz, varWorldPos );" << Endl;
} else {
- fragmentShader << "\tshadowFac = shadow_map_occl;" << Endl;
+ fragmentShader << " shadowFac = shadow_map_occl;" << Endl;
}
if (specularEnabled) {
@@ -1276,14 +1285,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
OutputDiffuseAreaLighting(fragmentShader, "varWorldPos", m_TempStr);
- fragmentShader << "\tlightAttenuation *= shadowFac;" << Endl;
+ fragmentShader << " lightAttenuation *= shadowFac;" << Endl;
AddTranslucencyIrradiance(fragmentShader, translucencyImage, m_TempStr, true);
- fragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ fragmentShader << " global_diffuse_light.rgb += lightAttenuation * "
"diffuseReflectionBSDF( world_normal, "
- << m_NormalizedDirection << ", view_vector, " << m_LightColor
- << ".rgb, 0.0 ).rgb;" << Endl;
+ << m_NormalizedDirection << ", " << m_LightColor
+ << ".rgb).rgb;" << Endl;
} else {
vertexShader.GenerateWorldPosition();
@@ -1304,19 +1313,19 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
m_RelativeDistance = m_TempStr;
m_RelativeDistance.append("_distance");
- fragmentShader << "\tvec3 " << m_RelativeDirection << " = varWorldPos - "
+ fragmentShader << " vec3 " << m_RelativeDirection << " = varWorldPos - "
<< m_LightPos << ".xyz;" << Endl;
- fragmentShader << "\tfloat " << m_RelativeDistance << " = length( "
+ fragmentShader << " float " << m_RelativeDistance << " = length( "
<< m_RelativeDirection << " );" << Endl;
- fragmentShader << "\tvec3 " << m_NormalizedDirection << " = "
+ fragmentShader << " vec3 " << m_NormalizedDirection << " = "
<< m_RelativeDirection << " / " << m_RelativeDistance << ";"
<< Endl;
if (enableSSDO) {
- fragmentShader << "\tshadowFac = shadow_map_occl * customMaterialShadow( "
+ fragmentShader << " shadowFac = shadow_map_occl * customMaterialShadow( "
<< m_NormalizedDirection << ", varWorldPos );" << Endl;
} else {
- fragmentShader << "\tshadowFac = shadow_map_occl;" << Endl;
+ fragmentShader << " shadowFac = shadow_map_occl;" << Endl;
}
addFunction(fragmentShader, "calculatePointLightAttenuation");
@@ -1324,13 +1333,13 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if (m_LightsAsSeparateUniforms) {
fragmentShader.AddUniform(m_LightAttenuation, "vec3");
fragmentShader
- << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation("
+ << " lightAttenuation = shadowFac * calculatePointLightAttenuation("
<< "vec3( " << m_LightAttenuation << ".x, " << m_LightAttenuation
<< ".y, " << m_LightAttenuation << ".z), " << m_RelativeDistance
<< ");" << Endl;
} else {
fragmentShader
- << "\tlightAttenuation = shadowFac * calculatePointLightAttenuation("
+ << " lightAttenuation = shadowFac * calculatePointLightAttenuation("
<< "vec3( " << m_LightConstantAttenuation << ", "
<< m_LightLinearAttenuation << ", " << m_LightQuadraticAttenuation
<< "), " << m_RelativeDistance << ");"
@@ -1341,10 +1350,10 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
AddTranslucencyIrradiance(fragmentShader, translucencyImage, m_TempStr, false);
- fragmentShader << "\tglobal_diffuse_light.rgb += lightAttenuation * "
+ fragmentShader << " global_diffuse_light.rgb += lightAttenuation * "
"diffuseReflectionBSDF( world_normal, "
- << "-" << m_NormalizedDirection << ", view_vector, "
- << m_LightColor << ".rgb, 0.0 ).rgb;" << Endl;
+ << "-" << m_NormalizedDirection << ", "
+ << m_LightColor << ".rgb).rgb;" << Endl;
if (specularEnabled) {
if (m_LightsAsSeparateUniforms)
@@ -1363,14 +1372,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
// Furthermore object_opacity is something that may come from the vertex pipeline or
// somewhere else.
// We leave it up to the vertex pipeline to figure it out.
- fragmentShader << "\tglobal_diffuse_light = vec4(global_diffuse_light.xyz * aoFactor, "
+ fragmentShader << " global_diffuse_light = vec4(global_diffuse_light.xyz * aoFactor, "
"object_opacity);"
- << Endl << "\tglobal_specular_light = vec3(global_specular_light.xyz);"
+ << Endl << " global_specular_light = vec3(global_specular_light.xyz);"
<< Endl;
} else // no lighting.
{
- fragmentShader << "\tvec4 global_diffuse_light = vec4(0.0, 0.0, 0.0, object_opacity);"
- << Endl << "\tvec3 global_specular_light = vec3(0.0, 0.0, 0.0);" << Endl;
+ fragmentShader << " vec4 global_diffuse_light = vec4(0.0, 0.0, 0.0, object_opacity);"
+ << Endl << " vec3 global_specular_light = vec3(0.0, 0.0, 0.0);" << Endl;
// We still have specular maps and such that could potentially use the fresnel variable.
fragmentHasSpecularAmount =
@@ -1379,19 +1388,19 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if (!hasEmissiveMap)
fragmentShader
- << "\tglobal_diffuse_light.rgb += diffuse_color.rgb * material_diffuse.rgb;"
+ << " global_diffuse_light.rgb += diffuse_color.rgb * material_diffuse.rgb;"
<< Endl;
// since we already modulate our material diffuse color
// into the light color we will miss it entirely if no IBL
// or light is used
if (hasLightmaps && !(m_Lights.size() || hasIblProbe))
- fragmentShader << "\tglobal_diffuse_light.rgb *= diffuse_color.rgb;" << Endl;
+ fragmentShader << " global_diffuse_light.rgb *= diffuse_color.rgb;" << Endl;
if (hasLighting && hasIblProbe) {
vertexShader.GenerateWorldNormal();
- fragmentShader << "\tglobal_diffuse_light.rgb += diffuse_color.rgb * aoFactor * "
+ fragmentShader << " global_diffuse_light.rgb += diffuse_color.rgb * aoFactor * "
"sampleDiffuse( tanFrame ).xyz;"
<< Endl;
@@ -1399,7 +1408,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader.AddUniform("material_specular", "vec4");
- fragmentShader << "\tglobal_specular_light.xyz += specularAmount * specularColor * "
+ fragmentShader << " global_specular_light.xyz += specularAmount * specularColor * "
"vec3(material_specular.xyz) * sampleGlossy( tanFrame, "
"view_vector, roughnessAmount ).xyz;"
<< Endl;
@@ -1407,7 +1416,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
if (hasImage) {
- fragmentShader.Append("\tvec4 texture_color;");
+ fragmentShader.Append(" vec4 texture_color;");
QT3DSU32 idx = 0;
for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
// Various maps are handled on a different locations
@@ -1431,18 +1440,18 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
lookupSwizzle);
if (texLodStr.empty()) {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << " = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ")"
<< lookupSwizzle.c_str() << ";" << Endl;
} else {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << "= textureLod( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ", "
<< texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
<< Endl;
}
if (image->m_Image.m_TextureData.m_TextureFlags.IsPreMultiplied() == true)
- fragmentShader << "\ttexture_color.rgb = texture_color.a > 0.0 ? "
+ fragmentShader << " texture_color.rgb = texture_color.a > 0.0 ? "
"texture_color.rgb / texture_color.a : vec3( 0, 0, 0 );"
<< Endl;
@@ -1454,27 +1463,38 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
// not premultiplied textures.
// If Z is 1, then we assume the incoming texture is already premultiplied, else
// we just read the rgb value.
- fragmentShader.Append("\tglobal_diffuse_light *= texture_color;");
+ fragmentShader.Append(" global_diffuse_light *= texture_color;");
break;
case ImageMapTypes::Specular:
-
fragmentShader.AddUniform("material_specular", "vec4");
- if (fragmentHasSpecularAmount) {
- fragmentShader.Append("\tglobal_specular_light.xyz += specularAmount * "
- "specularColor * texture_color.xyz * "
- "material_specular.xyz;");
+ if (image->m_Image.m_TextureData.m_Texture->GetTextureDetails().m_Format != NVRenderTextureFormats::RGBE8) {
+ if (fragmentHasSpecularAmount) {
+ fragmentShader.Append(" global_specular_light.xyz += specularAmount * "
+ "specularColor * texture_color.xyz * "
+ "material_specular.xyz;");
+ } else {
+ fragmentShader.Append(" global_specular_light.xyz += texture_color.xyz * "
+ "material_specular.xyz;");
+ }
+ fragmentShader.Append(" global_diffuse_light.a *= texture_color.a;");
} else {
- fragmentShader.Append("\tglobal_specular_light.xyz += texture_color.xyz * "
- "material_specular.xyz;");
+ // RGBE map
+ if (fragmentHasSpecularAmount) {
+ fragmentShader.Append(" global_specular_light.xyz += specularAmount * "
+ "specularColor * texture_color.xyz * pow(2.0, texture_color.a * 255.0 - 128.0);"
+ "material_specular.xyz;");
+ } else {
+ fragmentShader.Append(" global_specular_light.xyz += texture_color.xyz * "
+ "material_specular.xyz * pow(2.0, texture_color.a * 255.0 - 128.0);");
+ }
}
- fragmentShader.Append("\tglobal_diffuse_light.a *= texture_color.a;");
break;
case ImageMapTypes::Opacity:
- fragmentShader.Append("\tglobal_diffuse_light.a *= texture_color.a;");
+ fragmentShader.Append(" global_diffuse_light.a *= texture_color.a;");
break;
case ImageMapTypes::Emissive:
fragmentShader.Append(
- "\tglobal_emission *= texture_color.xyz * texture_color.a;");
+ " global_emission *= texture_color.xyz * texture_color.a;");
break;
default:
QT3DS_ASSERT(false); // fallthrough intentional
@@ -1486,27 +1506,27 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
if (enableAlphaTest) {
fragmentShader.AddUniform("alphaOpRef", "vec2");
fragmentShader.Append(
- "\tif (dot(vec2(global_diffuse_light.a, 1.0), alphaOpRef) <= 0.0)\n"
- "\t\tdiscard;");
+ " if (dot(vec2(global_diffuse_light.a, 1.0), alphaOpRef) <= 0.0)\n"
+ " discard;");
}
if (hasEmissiveMap) {
- fragmentShader.Append("\tglobal_diffuse_light.rgb += global_emission.rgb;");
+ fragmentShader.Append(" global_diffuse_light.rgb += global_emission.rgb;");
}
// Ensure the rgb colors are in range.
- fragmentShader.Append("\tfragOutput = vec4( clamp( vertColor * global_diffuse_light.xyz + "
+ fragmentShader.Append(" fragOutput = vec4( clamp( vertColor * global_diffuse_light.xyz + "
"global_specular_light.xyz, 0.0, 65519.0 ), global_diffuse_light.a "
");");
if (VertexGenerator().HasActiveWireframe()) {
fragmentShader.Append("vec3 edgeDistance = varEdgeDistance * gl_FragCoord.w;");
fragmentShader.Append(
- "\tfloat d = min(min(edgeDistance.x, edgeDistance.y), edgeDistance.z);");
- fragmentShader.Append("\tfloat mixVal = smoothstep(0.0, 1.0, d);"); // line width 1.0
+ " float d = min(min(edgeDistance.x, edgeDistance.y), edgeDistance.z);");
+ fragmentShader.Append(" float mixVal = smoothstep(0.0, 1.0, d);"); // line width 1.0
fragmentShader.Append(
- "\tfragOutput = mix( vec4(0.0, 1.0, 0.0, 1.0), fragOutput, mixVal);");
+ " fragOutput = mix( vec4(0.0, 1.0, 0.0, 1.0), fragOutput, mixVal);");
}
}
@@ -1552,13 +1572,13 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
vertexShader.AddIncoming("attr_pos", "vec3");
vertexShader.AddUniform("model_view_projection", "mat4");
vertexShader.Append("void main() {");
- vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
- vertexShader.Append("\tvec3 uTransform;");
- vertexShader.Append("\tvec3 vTransform;");
+ vertexShader.Append(" gl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" vec3 uTransform;");
+ vertexShader.Append(" vec3 vTransform;");
- fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+ fragmentShader << " float global_opacity = object_opacity;" << Endl;
- fragmentShader.Append("\tvec4 texture_color;");
+ fragmentShader.Append(" vec4 texture_color;");
QT3DSU32 idx = 0;
for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
// Various maps are handled on a different locations
@@ -1583,11 +1603,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
lookupSwizzle);
if (texLodStr.empty()) {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << " = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ")"
<< lookupSwizzle.c_str() << ";" << Endl;
} else {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << "= textureLod( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ", "
<< texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
<< Endl;
@@ -1598,7 +1618,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
case ImageMapTypes::LightmapShadow:
case ImageMapTypes::Specular:
case ImageMapTypes::Opacity:
- fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ fragmentShader.Append(" global_opacity *= texture_color.a;");
break;
default:
break;
@@ -1606,9 +1626,9 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
fragmentShader.AddUniform("alphaOpRef", "vec2");
- fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
- "\t\tdiscard;");
- fragmentShader.Append("\tfragOutput = vec4(0.0);");
+ fragmentShader.Append(" if (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ " discard;");
+ fragmentShader.Append(" fragOutput = vec4(0.0);");
fragmentShader.Append("}");
vertexShader.Append("}");
@@ -1663,16 +1683,16 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
vertexShader.AddOutgoing("world_pos", "vec4");
vertexShader.Append("void main() {");
- vertexShader.Append("\tvec3 uTransform;");
- vertexShader.Append("\tvec3 vTransform;");
- vertexShader.Append("\tworld_pos = model_matrix * vec4( attr_pos, 1.0 );");
- vertexShader.Append("\tworld_pos /= world_pos.w;");
- vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
- vertexShader.Append("\traw_pos = vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" vec3 uTransform;");
+ vertexShader.Append(" vec3 vTransform;");
+ vertexShader.Append(" world_pos = model_matrix * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" world_pos /= world_pos.w;");
+ vertexShader.Append(" gl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" raw_pos = vec4( attr_pos, 1.0 );");
- fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+ fragmentShader << " float global_opacity = object_opacity;" << Endl;
- fragmentShader.Append("\tvec4 texture_color;");
+ fragmentShader.Append(" vec4 texture_color;");
QT3DSU32 idx = 0;
for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
// Various maps are handled on different locations
@@ -1697,11 +1717,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
lookupSwizzle);
if (texLodStr.empty()) {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << " = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ")"
<< lookupSwizzle.c_str() << ";" << Endl;
} else {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << "= textureLod( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ", "
<< texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
<< Endl;
@@ -1712,7 +1732,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
case ImageMapTypes::LightmapShadow:
case ImageMapTypes::Specular:
case ImageMapTypes::Opacity:
- fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ fragmentShader.Append(" global_opacity *= texture_color.a;");
break;
default:
break;
@@ -1721,14 +1741,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
fragmentShader.AddUniform("camera_position", "vec3");
fragmentShader.AddUniform("camera_properties", "vec2");
- fragmentShader.Append("\tvec3 camPos = vec3(camera_position.x, camera_position.y, "
+ fragmentShader.Append(" vec3 camPos = vec3(camera_position.x, camera_position.y, "
"-camera_position.z);");
- fragmentShader.Append("\tfloat dist = length(world_pos.xyz - camPos);");
- fragmentShader.Append("\tdist = max((dist - 1.0) / (camera_properties.y - 1.0), 0.0);");
+ fragmentShader.Append(" float dist = length(world_pos.xyz - camPos);");
+ fragmentShader.Append(" dist = max((dist - 1.0) / (camera_properties.y - 1.0), 0.0);");
fragmentShader.AddUniform("alphaOpRef", "vec2");
- fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
- "\t\tdist = 1.0;");
- fragmentShader.Append("\tfragOutput = vec4(dist);");
+ fragmentShader.Append(" if (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ " dist = 1.0;");
+ fragmentShader.Append(" fragOutput = vec4(dist);");
fragmentShader.Append("}");
vertexShader.Append("}");
@@ -1781,14 +1801,14 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
vertexShader.AddOutgoing("outDepth", "vec3");
vertexShader.Append("void main() {");
- vertexShader.Append("\tvec3 uTransform;");
- vertexShader.Append("\tvec3 vTransform;");
- vertexShader.Append("\tgl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
- vertexShader.Append("\toutDepth.x = gl_Position.z / gl_Position.w;");
+ vertexShader.Append(" vec3 uTransform;");
+ vertexShader.Append(" vec3 vTransform;");
+ vertexShader.Append(" gl_Position = model_view_projection * vec4( attr_pos, 1.0 );");
+ vertexShader.Append(" outDepth.x = gl_Position.z / gl_Position.w;");
- fragmentShader << "\tfloat global_opacity = object_opacity;" << Endl;
+ fragmentShader << " float global_opacity = object_opacity;" << Endl;
- fragmentShader.Append("\tvec4 texture_color;");
+ fragmentShader.Append(" vec4 texture_color;");
QT3DSU32 idx = 0;
for (SRenderableImage *image = m_FirstImage; image; image = image->m_NextImage, ++idx) {
// Various maps are handled on different locations
@@ -1813,11 +1833,11 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
lookupSwizzle);
if (texLodStr.empty()) {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << " = texture2D( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << " = texture2D( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ")"
<< lookupSwizzle.c_str() << ";" << Endl;
} else {
- fragmentShader << "\ttexture_color" << texSwizzle.c_str() << "= textureLod( "
+ fragmentShader << " texture_color" << texSwizzle.c_str() << "= textureLod( "
<< m_ImageSampler << ", " << m_ImageFragCoords << ", "
<< texLodStr.c_str() << " )" << lookupSwizzle.c_str() << ";"
<< Endl;
@@ -1828,7 +1848,7 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
case ImageMapTypes::LightmapShadow:
case ImageMapTypes::Specular:
case ImageMapTypes::Opacity:
- fragmentShader.Append("\tglobal_opacity *= texture_color.a;");
+ fragmentShader.Append(" global_opacity *= texture_color.a;");
break;
default:
break;
@@ -1836,10 +1856,10 @@ struct SShaderGenerator : public IDefaultMaterialShaderGenerator
}
fragmentShader.AddUniform("alphaOpRef", "vec2");
- fragmentShader.Append("\tfloat depth = (outDepth.x + 1.0) * 0.5;");
- fragmentShader.Append("\tif (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
- "\t\tdepth = 1.0;");
- fragmentShader.Append("\tfragOutput = vec4(depth);");
+ fragmentShader.Append(" float depth = (outDepth.x + 1.0) * 0.5;");
+ fragmentShader.Append(" if (dot(vec2(global_opacity, 1.0), alphaOpRef) <= 0.0)\n"
+ " depth = 1.0;");
+ fragmentShader.Append(" fragOutput = vec4(depth);");
fragmentShader.Append("}");
vertexShader.Append("}");
diff --git a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp
index cb629cc..fdab6d4 100644
--- a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp
+++ b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.cpp
@@ -90,6 +90,8 @@ namespace render {
return sizeof(SApplyDepthValue);
case CommandTypes::ApplyInstanceValue:
return sizeof(SApplyInstanceValue);
+ case CommandTypes::ApplyDepth:
+ return sizeof(SApplyDepth);
case CommandTypes::ApplyBlending:
return sizeof(SApplyBlending);
case CommandTypes::ApplyRenderState:
@@ -109,6 +111,8 @@ namespace render {
return sizeof(SAllocateDataBuffer);
case CommandTypes::ApplyDataBufferValue:
return sizeof(SApplyDataBufferValue);
+ case CommandTypes::ApplyCulling:
+ return sizeof(SApplyCulling);
default:
break;
}
@@ -153,12 +157,18 @@ namespace render {
case CommandTypes::ApplyInstanceValue:
CopyConstructCommandT<SApplyInstanceValue>(inDataBuffer, inCommand, inStrTable);
break;
+ case CommandTypes::ApplyDepth:
+ CopyConstructCommandT<SApplyDepth>(inDataBuffer, inCommand, inStrTable);
+ break;
case CommandTypes::ApplyBlending:
CopyConstructCommandT<SApplyBlending>(inDataBuffer, inCommand, inStrTable);
break;
case CommandTypes::ApplyRenderState:
CopyConstructCommandT<SApplyRenderState>(inDataBuffer, inCommand, inStrTable);
break;
+ case CommandTypes::ApplyCulling:
+ CopyConstructCommandT<SApplyCulling>(inDataBuffer, inCommand, inStrTable);
+ break;
case CommandTypes::ApplyBlitFramebuffer:
CopyConstructCommandT<SApplyBlitFramebuffer>(inDataBuffer, inCommand, inStrTable);
break;
@@ -402,7 +412,6 @@ struct SDynamicObjClassImpl : public IDynamicObjectClass
CRegisteredString m_Id;
NVConstDataRef<SPropertyDefinition> m_PropertyDefinitions;
QT3DSU32 m_PropertySectionByteSize;
- QT3DSU32 m_BaseObjectSize;
GraphObjectTypes::Enum m_GraphObjectType;
QT3DSU8 *m_PropertyDefaultData;
NVConstDataRef<SCommand *> m_RenderCommands;
@@ -414,14 +423,13 @@ struct SDynamicObjClassImpl : public IDynamicObjectClass
SDynamicObjClassImpl(
NVAllocatorCallback &alloc, CRegisteredString id,
NVConstDataRef<SPropertyDefinition> definitions, QT3DSU32 propertySectionByteSize,
- QT3DSU32 baseObjectSize, GraphObjectTypes::Enum objectType, QT3DSU8 *propDefaultData,
+ GraphObjectTypes::Enum objectType, QT3DSU8 *propDefaultData,
bool inRequiresDepthTexture = false,
NVRenderTextureFormats::Enum inOutputFormat = NVRenderTextureFormats::RGBA8)
: m_Allocator(&alloc)
, m_Id(id)
, m_PropertyDefinitions(definitions)
, m_PropertySectionByteSize(propertySectionByteSize)
- , m_BaseObjectSize(baseObjectSize)
, m_GraphObjectType(objectType)
, m_PropertyDefaultData(propDefaultData)
, mRefCount(0)
@@ -502,7 +510,6 @@ struct SDynamicObjClassImpl : public IDynamicObjectClass
}
QT3DSU32 GetPropertySectionByteSize() const override { return m_PropertySectionByteSize; }
const QT3DSU8 *GetDefaultValueBuffer() const override { return m_PropertyDefaultData; }
- QT3DSU32 GetBaseObjectSize() const override { return m_BaseObjectSize; }
GraphObjectTypes::Enum GraphObjectType() const override { return m_GraphObjectType; }
const SPropertyDefinition *FindDefinition(CRegisteredString &str) const
{
@@ -641,7 +648,7 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
}
bool Register(CRegisteredString inName,
- NVConstDataRef<SPropertyDeclaration> inProperties, QT3DSU32 inBaseObjectSize,
+ NVConstDataRef<SPropertyDeclaration> inProperties,
GraphObjectTypes::Enum inGraphObjectType) override
{
if (IsRegistered(inName)) {
@@ -677,7 +684,7 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
memZero(defaultData, defaultSize);
SDynamicObjClassImpl *theClass = new (allocData)
SDynamicObjClassImpl(m_Allocator, inName, toDataRef(defPtr, inProperties.size()),
- dataSectionSize, inBaseObjectSize, inGraphObjectType, defaultData);
+ dataSectionSize, inGraphObjectType, defaultData);
m_Classes.insert(eastl::make_pair(inName, theClass));
return true;
}
@@ -867,12 +874,10 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
QT3DS_ASSERT(false);
return NULL;
}
- QT3DSU32 totalObjectSize = theClass->m_BaseObjectSize + theClass->m_PropertySectionByteSize;
+ QT3DSU32 totalObjectSize = theClass->m_PropertySectionByteSize + sizeof(SDynamicObject);
SDynamicObject *retval = reinterpret_cast<SDynamicObject *>(inSceneGraphAllocator.allocate(
totalObjectSize, inClassName.c_str(), __FILE__, __LINE__));
- new (retval)
- SDynamicObject(theClass->m_GraphObjectType, inClassName,
- theClass->m_PropertySectionByteSize, theClass->m_BaseObjectSize);
+ new (retval) SDynamicObject(inClassName, theClass->m_PropertySectionByteSize);
memCopy(retval->GetDataSectionBegin(), theClass->m_PropertyDefaultData,
theClass->m_PropertySectionByteSize);
return retval;
@@ -1173,7 +1178,7 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
QT3DSU32 numRenderCommands = theClass->m_RenderCommands.size();
new (theClass) SDynamicObjClassImpl(
m_Allocator, theClass->m_Id, theClass->m_PropertyDefinitions,
- theClass->m_PropertySectionByteSize, theClass->m_BaseObjectSize,
+ theClass->m_PropertySectionByteSize,
theClass->m_GraphObjectType, theClass->m_PropertyDefaultData,
theClass->m_RequiresDepthTexture, theClass->m_OutputFormat);
@@ -1249,9 +1254,13 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
// uniform sampler2D propName; \
// uniform int flag##propName; \
// uniform vec4 propName##Info; \
+ // uniform vec3 propName##TransformU; \
+ // uniform vec3 propName##TransformV; \
// vec4 texture2D_##propName(vec2 uv) \
// { \
- // return GetTextureValue( propName, uv, propName##Info.z ); \
+ // vec3 tuv(uv, 1.0); \
+ // vec2 uv2(dot(propName##TransformU, tuv), dot(propName##TransformV, tuv)); \
+ // return GetTextureValue( propName, uv2, propName##Info.z ); \
// }
//
// #define SNAPPER_SAMPLER2DWITHDEFAULT(propName, propNiceName, texFilter, texWrap, defaultPath, showUI ) \
@@ -1267,22 +1276,31 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
QString snapperSamplerCube = QStringLiteral("SNAPPER_SAMPLERCUBE(");
QString endingBracket = QStringLiteral(")");
+ const auto insertSnapperStr = [](const QString &parameter) {
+ QString insertStr;
+ QTextStream stream(&insertStr);
+ stream << "uniform sampler2D " << parameter << ";\n";
+ stream << "uniform int flag" << parameter << ";\n";
+ stream << "uniform vec4 " << parameter << "Info;\n";
+ stream << "uniform vec3 " << parameter << "TransformU;\n";
+ stream << "uniform vec3 " << parameter << "TransformV;\n";
+ stream << "vec2 transformCoord" << parameter << "(vec2 uv) { return vec2(dot("
+ << parameter << "TransformU, vec3(uv, 1.0)), dot("
+ << parameter << "TransformV, vec3(uv, 1.0))); }\n";
+ stream << "vec4 texture2D_" << parameter << "(vec2 uv) "
+ << "{ return GetTextureValue( " << parameter
+ << ", transformCoord" << parameter << "(uv), "
+ << parameter << "Info.z ); }\n";
+ return insertStr;
+ };
+
while ((beginIndex = str.indexOf(snapperSampler, beginIndex)) >= 0) {
int endIndex = str.indexOf(endingBracket, beginIndex);
const QStringList list = getParameters(str, beginIndex + snapperSampler.length(),
endIndex);
str.remove(beginIndex, endIndex - beginIndex + 1);
- if (list.size() == 5) {
- QString insertStr;
- QTextStream stream(&insertStr);
- stream << "uniform sampler2D " << list[0] << ";\n";
- stream << "uniform int flag" << list[0] << ";\n";
- stream << "vec4 " << list[0] << "Info;\n";
- stream << "vec4 texture2D_" << list[0] << "(vec2 uv) "
- << "{ return GetTextureValue( " << list[0] << ", uv, "
- << list[0] <<"Info.z ); }\n";
- str.insert(beginIndex, insertStr);
- }
+ if (list.size() == 5)
+ str.insert(beginIndex, insertSnapperStr(list[0]));
}
beginIndex = 0;
while ((beginIndex = str.indexOf(snapperSamplerDefault, beginIndex)) >= 0) {
@@ -1290,17 +1308,8 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
const QStringList list = getParameters(str, beginIndex + snapperSamplerDefault.length(),
endIndex);
str.remove(beginIndex, endIndex - beginIndex + 1);
- if (list.size() == 5) {
- QString insertStr;
- QTextStream stream(&insertStr);
- stream << "uniform sampler2D " << list[0] << ";\n";
- stream << "uniform int flag" << list[0] << ";\n";
- stream << "vec4 " << list[0] << "Info;\n";
- stream << "vec4 texture2D_" << list[0] << "(vec2 uv) "
- << "{ return GetTextureValue( " << list[0] << ", uv, "
- << list[0] <<"Info.z ); }\n";
- str.insert(beginIndex, insertStr);
- }
+ if (list.size() == 5)
+ str.insert(beginIndex, insertSnapperStr(list[0]));
}
beginIndex = 0;
while ((beginIndex = str.indexOf(snapperSamplerCube, beginIndex)) >= 0) {
@@ -1367,11 +1376,9 @@ struct SDynamicObjectSystemImpl : public IDynamicObjectSystem
if (strstr(inProgramSource, "SNAPPER_SAMPLER")) {
QString programSource(inProgramSource);
insertSnapperDirectives(programSource);
- QByteArray data = programSource.toLatin1();
- const char *source = data.constData();
- m_VertShader.append(source);
- m_FragShader.append(source);
+ m_VertShader.append(programSource);
+ m_FragShader.append(programSource);
} else {
m_VertShader.append(inProgramSource);
m_FragShader.append(inProgramSource);
diff --git a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h
index 5379df2..a6e3be7 100644
--- a/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h
+++ b/src/runtimerender/Qt3DSRenderDynamicObjectSystem.h
@@ -162,7 +162,6 @@ namespace render {
virtual NVConstDataRef<dynamic::SPropertyDefinition> GetProperties() const = 0;
virtual QT3DSU32 GetPropertySectionByteSize() const = 0;
virtual const QT3DSU8 *GetDefaultValueBuffer() const = 0;
- virtual QT3DSU32 GetBaseObjectSize() const = 0;
virtual GraphObjectTypes::Enum GraphObjectType() const = 0;
virtual const dynamic::SPropertyDefinition *
FindPropertyByName(CRegisteredString inName) const = 0;
@@ -183,7 +182,7 @@ namespace render {
virtual bool Register(CRegisteredString inName,
NVConstDataRef<dynamic::SPropertyDeclaration> inProperties,
- QT3DSU32 inBaseObjectSize, GraphObjectTypes::Enum inGraphObjectType) = 0;
+ GraphObjectTypes::Enum inGraphObjectType) = 0;
virtual bool Unregister(CRegisteredString inName) = 0;
diff --git a/src/runtimerender/Qt3DSRenderDynamicObjectSystemCommands.h b/src/runtimerender/Qt3DSRenderDynamicObjectSystemCommands.h
index 857dfa9..0628d8d 100644
--- a/src/runtimerender/Qt3DSRenderDynamicObjectSystemCommands.h
+++ b/src/runtimerender/Qt3DSRenderDynamicObjectSystemCommands.h
@@ -54,6 +54,7 @@ namespace render {
// Apply the depth buffer as an input texture.
ApplyDepthValue,
Render, // Render to current FBO
+ ApplyDepth,
ApplyBlending,
ApplyRenderState, // apply a render state
ApplyBlitFramebuffer,
@@ -63,6 +64,7 @@ namespace render {
ApplyImageValue,
AllocateDataBuffer,
ApplyDataBufferValue,
+ ApplyCulling
};
};
@@ -83,7 +85,8 @@ namespace render {
QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(AllocateImage) \
QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyImageValue) \
QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(AllocateDataBuffer) \
- QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyDataBufferValue)
+ QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyDataBufferValue) \
+ QT3DS_RENDER_EFFECTS_HANDLE_COMMAND_TYPES(ApplyCulling)
// All commands need at least two constructors. One for when they are created that should
// setup all their member variables and one for when we are copying commands from an outside
@@ -473,6 +476,41 @@ namespace render {
}
};
+ struct SApplyCulling : public SCommand
+ {
+ NVRenderFaces::Enum m_CullMode;
+ SApplyCulling(NVRenderFaces::Enum cullMode)
+ : SCommand(CommandTypes::ApplyCulling)
+ , m_CullMode(cullMode)
+ {
+ }
+ SApplyCulling(const SApplyCulling &inOther, IStringTable &)
+ : SCommand(CommandTypes::ApplyCulling)
+ , m_CullMode(inOther.m_CullMode)
+ {
+ }
+ };
+
+ struct SApplyDepth : public SCommand
+ {
+ NVRenderBoolOp::Enum m_depthFunc;
+ bool m_depthMask;
+
+ SApplyDepth(NVRenderBoolOp::Enum depthFunc, bool depthMask)
+ : SCommand(CommandTypes::ApplyDepth)
+ , m_depthFunc(depthFunc)
+ , m_depthMask(depthMask)
+ {
+ }
+
+ SApplyDepth(const SApplyDepth &other, IStringTable &)
+ : SCommand(CommandTypes::ApplyDepth)
+ , m_depthFunc(other.m_depthFunc)
+ , m_depthMask(other.m_depthMask)
+ {
+ }
+ };
+
struct SApplyBlending : public SCommand
{
NVRenderSrcBlendFunc::Enum m_SrcBlendFunc;
diff --git a/src/runtimerender/Qt3DSRenderEffectSystem.cpp b/src/runtimerender/Qt3DSRenderEffectSystem.cpp
index b10345c..081ad7e 100644
--- a/src/runtimerender/Qt3DSRenderEffectSystem.cpp
+++ b/src/runtimerender/Qt3DSRenderEffectSystem.cpp
@@ -511,8 +511,6 @@ struct SEffectSystem : public IEffectSystem
TShaderMap m_ShaderMap;
NVScopedRefCounted<NVRenderDepthStencilState> m_DefaultStencilState;
nvvector<NVScopedRefCounted<NVRenderDepthStencilState>> m_DepthStencilStates;
- nvvector<TAllocatedImageEntry> m_AllocatedImages;
- nvvector<SEffect::TImageMapHash *> m_effectImageMaps;
volatile QT3DSI32 mRefCount;
@@ -525,8 +523,6 @@ struct SEffectSystem : public IEffectSystem
, m_Contexts(inContext.GetAllocator(), "SEffectSystem::m_Contexts")
, m_ShaderMap(inContext.GetAllocator(), "SEffectSystem::m_ShaderMap")
, m_DepthStencilStates(inContext.GetAllocator(), "SEffectSystem::m_DepthStencilStates")
- , m_AllocatedImages(inContext.GetAllocator(), "SEffectSystem::m_AllocatedImages")
- , m_effectImageMaps(inContext.GetAllocator(), "SEffectSystem::m_effectImageMaps")
, mRefCount(0)
{
}
@@ -541,18 +537,6 @@ struct SEffectSystem : public IEffectSystem
for (QT3DSU32 idx = 0, end = m_Contexts.size(); idx < end; ++idx)
NVDelete(m_Allocator, m_Contexts[idx]);
m_Contexts.clear();
-
- for (QT3DSU32 idx = 0; idx < m_AllocatedImages.size(); ++idx) {
- SImage *pImage = m_AllocatedImages[idx].second;
- QT3DS_FREE(m_CoreContext.GetAllocator(), pImage);
- }
- for (QT3DSU32 idx = 0; idx < m_effectImageMaps.size(); ++idx) {
- auto *effmap = m_effectImageMaps[idx];
- effmap->~nvhash_map();
- QT3DS_FREE(m_CoreContext.GetAllocator(), effmap);
- }
- m_effectImageMaps.clear();
- m_AllocatedImages.clear();
}
SEffectContext &GetEffectContext(SEffect &inEffect)
@@ -601,7 +585,7 @@ struct SEffectSystem : public IEffectSystem
if (IsEffectRegistered(inName))
return false;
- m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties, sizeof(SEffect),
+ m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties,
GraphObjectTypes::Effect);
IDynamicObjectClass &theClass =
*m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
@@ -689,7 +673,7 @@ struct SEffectSystem : public IEffectSystem
{
if (IsEffectRegistered(inName))
return false;
- m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties, sizeof(SEffect),
+ m_CoreContext.GetDynamicObjectSystemCore().Register(inName, inProperties,
GraphObjectTypes::Effect);
IDynamicObjectClass &theClass =
*m_CoreContext.GetDynamicObjectSystemCore().GetDynamicObjectClass(inName);
@@ -818,10 +802,12 @@ struct SEffectSystem : public IEffectSystem
return NULL;
StaticAssert<(sizeof(SEffect) % 4 == 0)>::valid_expression();
- SEffect *theEffect = (SEffect *)m_CoreContext.GetDynamicObjectSystemCore().CreateInstance(
+ SDynamicObject *dynamicObject = m_CoreContext.GetDynamicObjectSystemCore().CreateInstance(
inEffectName, inSceneGraphAllocator);
- theEffect->Initialize();
- return theEffect;
+
+ SEffect *effect = QT3DS_NEW(inSceneGraphAllocator, SEffect)(dynamicObject);
+ effect->Initialize();
+ return effect;
}
void AllocateBuffer(SEffect &inEffect, const SAllocateBuffer &inCommand, QT3DSU32 inFinalWidth,
@@ -1070,35 +1056,43 @@ struct SEffectSystem : public IEffectSystem
if (theConstant) {
if (theConstant->GetShaderConstantType() == inPropertyType) {
if (inPropertyType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
- StaticAssert<sizeof(CRegisteredString)
- == sizeof(NVRenderTexture2DPtr)>::valid_expression();
CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(inDataPtr);
- bool needsAlphaMultiply = true;
- NVRenderTexture2D *theTexture = nullptr;
- if (theStrPtr->IsValid() && inEffect.m_imageMaps) {
- SImage *image = (*inEffect.m_imageMaps)[inPropertyName];
- if (image) {
- if (image->m_ImagePath != *theStrPtr) {
- image->m_ImagePath = *theStrPtr;
- image->m_Flags.SetDirty(true);
- } else {
- if (image->m_OffscreenRendererId.IsValid()) {
- IOffscreenRenderManager &theOffscreenRenderer(
- m_Context->GetOffscreenRenderManager());
- SOffscreenRenderResult theResult
- = theOffscreenRenderer.GetRenderedItem(*theStrPtr);
- needsAlphaMultiply = false;
- theTexture = theResult.m_Texture;
- } else {
- needsAlphaMultiply = true;
- theTexture = image->m_LoadedTextureData->m_Texture;
- }
- }
+
+ SImage *image = inEffect.getImage(*theStrPtr);
+ if (image && image->m_TextureData.m_Texture) {
+ CRegisteredString strU = m_Context->GetStringTable().RegisterStr(
+ QString::fromLatin1(inPropertyName.c_str()) + "TransformU");
+ CRegisteredString strV = m_Context->GetStringTable().RegisterStr(
+ QString::fromLatin1(inPropertyName.c_str()) + "TransformV");
+ qt3ds::render::NVRenderShaderConstantBase *transformU =
+ inShader.GetShaderConstant(strU);
+ qt3ds::render::NVRenderShaderConstantBase *transformV =
+ inShader.GetShaderConstant(strV);
+ image->CalculateTextureTransform();
+ QT3DSMat44 textureTransform = image->m_TextureTransform;
+ if (image->m_TextureData.m_TextureFlags.IsInvertUVCoords()) {
+ QT3DSMat44 invertCoordsMat(QT3DSMat44::createIdentity());
+ invertCoordsMat.scale(QT3DSVec4(1.0f, -1.0f, 1.0f, 1.0f));
+ invertCoordsMat.setPosition(QT3DSVec3(0.0f, 1.0f, 0.0f));
+ textureTransform = textureTransform * invertCoordsMat;
+ }
+ const QT3DSF32 *dataPtr(textureTransform.front());
+ inShader.SetPropertyValue(transformU,
+ QT3DSVec3(dataPtr[0], dataPtr[4], dataPtr[12]));
+ inShader.SetPropertyValue(transformV,
+ QT3DSVec3(dataPtr[1], dataPtr[5], dataPtr[13]));
+ auto *texture = image->m_TextureData.m_Texture;
+ texture->SetTextureWrapS(image->m_HorizontalTilingMode);
+ texture->SetTextureWrapT(image->m_VerticalTilingMode);
+ texture->SetMinFilter(image->m_MinFilter);
+ texture->SetMagFilter(image->m_MagFilter);
+ if (inDefinition.m_MinFilterOp != NVRenderTextureMinifyingOp::Nearest
+ && inDefinition.m_MinFilterOp != NVRenderTextureMinifyingOp::Linear
+ && !texture->GetNumMipmaps()) {
+ texture->GenerateMipmaps();
}
+ inShader.SetPropertyValue(theConstant, image->m_TextureData.m_Texture);
}
- GetEffectContext(inEffect).SetTexture(
- inShader, inPropertyName, theTexture, needsAlphaMultiply,
- m_TextureStringBuilder, m_TextureStringBuilder2, &inDefinition);
} else if (inPropertyType == NVRenderShaderDataTypes::NVRenderImage2DPtr) {
StaticAssert<sizeof(CRegisteredString)
== sizeof(NVRenderTexture2DPtr)>::valid_expression();
@@ -1136,12 +1130,12 @@ struct SEffectSystem : public IEffectSystem
if (inCommand.m_PropertyName.IsValid()) {
bool canGetData =
inCommand.m_ValueOffset + getSizeofShaderDataType(inCommand.m_ValueType)
- <= inEffect.m_DataSectionByteSize;
+ <= inEffect.m_dynamicObject->m_DataSectionByteSize;
if (canGetData == false) {
QT3DS_ASSERT(false);
return;
}
- QT3DSU8 *dataPtr = inEffect.GetDataSectionBegin() + inCommand.m_ValueOffset;
+ QT3DSU8 *dataPtr = inEffect.m_dynamicObject->GetDataSectionOffset(inCommand.m_ValueOffset);
const SPropertyDefinition *theDefinition =
inClass.m_DynamicClass->FindPropertyByName(inCommand.m_PropertyName);
if (theDefinition)
@@ -1157,7 +1151,7 @@ struct SEffectSystem : public IEffectSystem
// This is fine, the property wasn't found and we continue, no problem.
if (!theConstant)
continue;
- QT3DSU8 *dataPtr = inEffect.GetDataSectionBegin() + theDefinition.m_Offset;
+ QT3DSU8 *dataPtr = inEffect.m_dynamicObject->GetDataSectionOffset(theDefinition.m_Offset);
DoApplyInstanceValue(inEffect, dataPtr, theDefinition.m_Name,
theDefinition.m_DataType, inShader, theDefinition);
}
@@ -1871,75 +1865,9 @@ struct SEffectSystem : public IEffectSystem
return *m_ResourceManager;
}
- QT3DSU32 FindAllocatedImage(CRegisteredString inName)
+ void prepareEffectForRender(SEffect &) override
{
- for (QT3DSU32 idx = 0, end = m_AllocatedImages.size(); idx < end; ++idx) {
- if (m_AllocatedImages[idx].first == inName)
- return idx;
- }
- return QT3DSU32(-1);
- }
- SEffect::TImageMapHash *newImageMap(NVAllocatorCallback &allocator)
- {
- const char *name = "SEffect::TImageMapHash";
- SEffect::TImageMapHash *ret
- = new (QT3DS_ALLOC(allocator, sizeof(SEffect::TImageMapHash), name))
- SEffect::TImageMapHash(allocator, name);
- m_effectImageMaps.push_back(ret);
- return ret;
- }
-
- void prepareEffectForRender(SEffect &inEffect) override
- {
- SEffectClass *theClass = GetEffectClass(inEffect.m_ClassName);
- if (!theClass)
- return;
-
- NVConstDataRef<SPropertyDefinition> theDefs = theClass->m_DynamicClass->GetProperties();
- for (QT3DSU32 idx = 0, end = theDefs.size(); idx < end; ++idx) {
- const SPropertyDefinition &theDefinition(theDefs[idx]);
- if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
- SImage *pImage = nullptr;
-
- QT3DSU8 *dataPtr = inEffect.GetDataSectionBegin() + theDefinition.m_Offset;
- StaticAssert<sizeof(CRegisteredString)
- == sizeof(NVRenderTexture2DPtr)>::valid_expression();
- CRegisteredString *theStrPtr = reinterpret_cast<CRegisteredString *>(dataPtr);
- if (theStrPtr->IsValid()) {
- IOffscreenRenderManager &theOffscreenRenderer(
- m_Context->GetOffscreenRenderManager());
-
- if (theOffscreenRenderer.HasOffscreenRenderer(*theStrPtr)) {
- theOffscreenRenderer.GetRenderedItem(*theStrPtr);
- } else {
- QT3DSU32 index = FindAllocatedImage(*theStrPtr);
- if (index == QT3DSU32(-1)) {
- pImage = QT3DS_NEW(m_CoreContext.GetAllocator(), SImage)();
- m_AllocatedImages.push_back(
- eastl::make_pair(*theStrPtr, pImage));
- } else {
- pImage = m_AllocatedImages[index].second;
- }
-
- if (!inEffect.m_imageMaps)
- inEffect.m_imageMaps = newImageMap(m_CoreContext.GetAllocator());
-
- if ((*inEffect.m_imageMaps)[theDefs[idx].m_Name] != pImage) {
- (*inEffect.m_imageMaps)[theDefs[idx].m_Name] = pImage;
- pImage->m_ImagePath = theDefs[idx].m_ImagePath;
- pImage->m_ImageShaderName = theDefs[idx].m_Name;
- pImage->m_VerticalTilingMode = theDefs[idx].m_CoordOp;
- pImage->m_HorizontalTilingMode = theDefs[idx].m_CoordOp;
- }
- }
- } else {
- if (!inEffect.m_imageMaps)
- inEffect.m_imageMaps = newImageMap(m_CoreContext.GetAllocator());
- (*inEffect.m_imageMaps)[theDefs[idx].m_Name] = nullptr;
- }
- }
- }
}
};
}
diff --git a/src/runtimerender/Qt3DSRenderGraphObjectSerializer.cpp b/src/runtimerender/Qt3DSRenderGraphObjectSerializer.cpp
index 358c5aa..bb75a40 100644
--- a/src/runtimerender/Qt3DSRenderGraphObjectSerializer.cpp
+++ b/src/runtimerender/Qt3DSRenderGraphObjectSerializer.cpp
@@ -122,6 +122,18 @@ struct SSerializerWriteContext
#endif
}
+ template <typename TObjType, typename Type>
+ void AddPtrOffset(Type type, const TObjType *inObject)
+ {
+ QT3DSU32 objOffset = m_MemoryBuffer.size() - m_DataBlockStart;
+ m_OffsetMap.insert(eastl::make_pair(inObject, objOffset));
+// In debug we keep stats on how much each type of object
+// contributes to the file size.
+#ifdef _DEBUG
+ GetStatEntry(type) += sizeof(TObjType);
+#endif
+ }
+
void Remap(CRegisteredString &inStr) { inStr.Remap(m_StrRemapMap); }
template <typename TObjType>
@@ -138,6 +150,7 @@ struct SSerializerWriteContext
}
void RemapMaterial(SGraphObject *&inPtr) { Remap(inPtr); }
+ void RemapDynamicObject(GraphObjectTypes::Enum type, SDynamicObject *&inPtr) { Remap(inPtr); }
template <typename TObjType>
void NullPtr(TObjType *&inPtr)
@@ -187,6 +200,7 @@ struct SSerializerReadContext : public SDataReader
}
}
void RemapMaterial(SGraphObject *&inPtr) { Remap(inPtr); }
+ void RemapDynamicObject(GraphObjectTypes::Enum type, SDynamicObject *&inPtr) { Remap(inPtr); }
// Nulling out pointers was done on write, so we don't do it here.
template <typename TObjType>
void NullPtr(TObjType *&)
@@ -202,6 +216,8 @@ struct SGraphObjectSerializerImpl
static TObjType *Read(SSerializerReadContext &inReadContext);
};
+static SDynamicObject *Write(GraphObjectTypes::Enum type, const SDynamicObject &ioObject, SSerializerWriteContext &outSavedBuffer);
+
struct SWriteRemapper
{
SSerializerWriteContext &m_WriteBuffer;
@@ -249,6 +265,11 @@ struct SWriteRemapper
}
}
}
+ void RemapDynamicObject(GraphObjectTypes::Enum inType, const SDynamicObject *inObj)
+ {
+ if (inObj)
+ Write(inType, *inObj, m_WriteBuffer);
+ }
template <typename TObjType>
void NullPtr(const TObjType *)
{
@@ -282,6 +303,21 @@ TObject *WriteGenericGraphObjectNoRemap(const TObject &ioObject,
return reinterpret_cast<TObject *>(outSavedBuffer.m_MemoryBuffer.begin() + theOffset);
}
+template <typename TObject, typename Type>
+TObject *WriteGenericGraphObjectNoRemap(Type type, const TObject &ioObject,
+ SSerializerWriteContext &outSavedBuffer)
+{
+ if (outSavedBuffer.HasWrittenObject(&ioObject))
+ return NULL;
+
+ outSavedBuffer.AddPtrOffset(type, &ioObject);
+ QT3DSU32 theOffset = outSavedBuffer.m_MemoryBuffer.size();
+ outSavedBuffer.m_MemoryBuffer.write(ioObject);
+ // Probably the buffer stays aligned but we want to work to keep it that way.
+ Align(outSavedBuffer.m_MemoryBuffer);
+ return reinterpret_cast<TObject *>(outSavedBuffer.m_MemoryBuffer.begin() + theOffset);
+}
+
template <typename TObject>
TObject *WriteGenericGraphObject(const TObject &ioObject, SSerializerWriteContext &outSavedBuffer)
{
@@ -335,7 +371,7 @@ void RemapProperties(SDynamicObject &ioObject, SSerializerWriteContext &outSaved
const SPropertyDefinition &theDef(theObjectProps[idx]);
if (theDef.m_DataType == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
CRegisteredString *theStr = reinterpret_cast<CRegisteredString *>(
- ioObject.GetDataSectionBegin() + theDef.m_Offset);
+ ioObject.GetDataSectionOffset(theDef.m_Offset));
outSavedBuffer.Remap(*theStr);
}
}
@@ -353,99 +389,32 @@ void RemapProperties(SDynamicObject &ioObject, SSerializerReadContext &inReadCon
const SPropertyDefinition &theDefinition(theProperties[idx]);
if (theDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
CRegisteredString *theString = reinterpret_cast<CRegisteredString *>(
- ioObject.GetDataSectionBegin() + theDefinition.m_Offset);
+ ioObject.GetDataSectionOffset(theDefinition.m_Offset));
inReadContext.Remap(*theString);
}
}
}
-template <>
-struct SGraphObjectSerializerImpl<SEffect>
+static SDynamicObject *Write(GraphObjectTypes::Enum type, const SDynamicObject &ioObject, SSerializerWriteContext &outSavedBuffer)
{
- static SGraphObject *Write(const SEffect &ioObject, SSerializerWriteContext &outSavedBuffer)
- {
- size_t itemOffset = outSavedBuffer.m_MemoryBuffer.size();
- SEffect *theNewEffect =
- static_cast<SEffect *>(WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer));
- if (theNewEffect) {
- theNewEffect->m_Context = NULL;
- // Writing it out is easy. Reading it back in means we have to have a correctly setup
- // IEffectManager so we
- // can remap strings.
- outSavedBuffer.m_MemoryBuffer.write(ioObject.GetDataSectionBegin(),
- ioObject.m_DataSectionByteSize);
- Align(outSavedBuffer.m_MemoryBuffer);
- SWriteRemapper theWriteRemapper(outSavedBuffer);
- // Write any connected objects.
- theNewEffect =
- reinterpret_cast<SEffect *>(outSavedBuffer.m_MemoryBuffer.begin() + itemOffset);
- theNewEffect->Remap(theWriteRemapper);
- }
- return theNewEffect;
- }
-
- static void Remap(SEffect &ioObject, SSerializerWriteContext &outSavedBuffer)
- {
- CRegisteredString theClassName = ioObject.m_ClassName;
- ioObject.Remap(outSavedBuffer);
- RemapProperties(ioObject, outSavedBuffer, theClassName);
- }
-
- static SEffect *Read(SSerializerReadContext &inReadContext)
- {
- SEffect *theEffect = ReadGenericGraphObject<SEffect>(inReadContext);
- if (theEffect) {
- inReadContext.m_CurrentPtr += theEffect->m_DataSectionByteSize;
- inReadContext.Align();
- RemapProperties(*theEffect, inReadContext);
- }
- return theEffect;
- }
-};
-
-template <>
-struct SGraphObjectSerializerImpl<SCustomMaterial>
-{
- static SGraphObject *Write(const SCustomMaterial &ioObject,
- SSerializerWriteContext &outSavedBuffer)
- {
- size_t itemOffset = outSavedBuffer.m_MemoryBuffer.size();
- SCustomMaterial *theNewObject = static_cast<SCustomMaterial *>(
- WriteGenericGraphObjectNoRemap(ioObject, outSavedBuffer));
- if (theNewObject) {
- // Writing it out is easy. Reading it back in means we have to have a correctly setup
- // IEffectManager so we
- // can remap strings.
- outSavedBuffer.m_MemoryBuffer.write(ioObject.GetDataSectionBegin(),
- ioObject.m_DataSectionByteSize);
- Align(outSavedBuffer.m_MemoryBuffer);
- theNewObject = reinterpret_cast<SCustomMaterial *>(outSavedBuffer.m_MemoryBuffer.begin()
- + itemOffset);
- SWriteRemapper theWriteRemapper(outSavedBuffer);
- // Write any connected objects.
- theNewObject->Remap(theWriteRemapper);
- }
- return theNewObject;
- }
-
- static void Remap(SCustomMaterial &ioObject, SSerializerWriteContext &outSavedBuffer)
- {
- CRegisteredString theClassName(ioObject.m_ClassName);
- ioObject.Remap(outSavedBuffer);
- RemapProperties(ioObject, outSavedBuffer, theClassName);
- }
-
- static SCustomMaterial *Read(SSerializerReadContext &inReadContext)
- {
- SCustomMaterial *theMaterial = ReadGenericGraphObject<SCustomMaterial>(inReadContext);
- if (theMaterial) {
- inReadContext.m_CurrentPtr += theMaterial->m_DataSectionByteSize;
- inReadContext.Align();
- RemapProperties(*theMaterial, inReadContext);
- }
- return theMaterial;
+ size_t itemOffset = outSavedBuffer.m_MemoryBuffer.size();
+ SDynamicObject *theNewObject = static_cast<SDynamicObject *>(
+ WriteGenericGraphObjectNoRemap(type, ioObject, outSavedBuffer));
+ if (theNewObject) {
+ // Writing it out is easy. Reading it back in means we have to have a correctly setup
+ // IEffectManager so we
+ // can remap strings.
+ outSavedBuffer.m_MemoryBuffer.write(ioObject.GetDataSectionBegin(),
+ ioObject.m_DataSectionByteSize);
+ Align(outSavedBuffer.m_MemoryBuffer);
+ theNewObject = reinterpret_cast<SDynamicObject *>(outSavedBuffer.m_MemoryBuffer.begin()
+ + itemOffset);
+ SWriteRemapper theWriteRemapper(outSavedBuffer);
+ // Write any connected objects.
+ theNewObject->Remap(theWriteRemapper);
}
-};
+ return theNewObject;
+}
#ifdef _INTEGRITYPLATFORM
template <typename TObjType>
diff --git a/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
index 1a418b1..5b02164 100644
--- a/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
+++ b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
@@ -205,6 +205,15 @@ struct SFactory : public IInputStreamFactory
}
return false;
}
+ bool GetPathForStream(IRefCountedInputStream *stream, QString &outFile) override
+ {
+ if (stream) {
+ SInputStream *theRealStream = static_cast<SInputStream *>(stream);
+ outFile = theRealStream->m_Path;
+ return true;
+ }
+ return false;
+ }
};
}
diff --git a/src/runtimerender/Qt3DSRenderInputStreamFactory.h b/src/runtimerender/Qt3DSRenderInputStreamFactory.h
index e82134b..fdc9e75 100644
--- a/src/runtimerender/Qt3DSRenderInputStreamFactory.h
+++ b/src/runtimerender/Qt3DSRenderInputStreamFactory.h
@@ -57,6 +57,7 @@ namespace render {
// else returns false
virtual bool GetPathForFile(const QString &inFilename, QString &outFile,
bool inQuiet = false) = 0;
+ virtual bool GetPathForStream(IRefCountedInputStream *stream, QString &outFile) = 0;
// Create an input stream factory using this foundation and an platform-optional app
// directory
diff --git a/src/runtimerender/Qt3DSRenderMaterialHelpers.h b/src/runtimerender/Qt3DSRenderMaterialHelpers.h
index afb799e..ad0325f 100644
--- a/src/runtimerender/Qt3DSRenderMaterialHelpers.h
+++ b/src/runtimerender/Qt3DSRenderMaterialHelpers.h
@@ -69,7 +69,7 @@ namespace render {
return NULL;
}
if (obj->m_Type == GraphObjectTypes::CustomMaterial)
- return static_cast<SCustomMaterial *>(obj)->m_NextSibling;
+ return static_cast<SCustomMaterial *>(obj)->m_MaterialSibling;
else if (obj->m_Type == GraphObjectTypes::DefaultMaterial)
return static_cast<SDefaultMaterial *>(obj)->m_NextSibling;
else
@@ -83,7 +83,7 @@ namespace render {
return;
}
if (obj.m_Type == GraphObjectTypes::CustomMaterial)
- static_cast<SCustomMaterial *>(&obj)->m_NextSibling = sibling;
+ static_cast<SCustomMaterial *>(&obj)->m_MaterialSibling = sibling;
else if (obj.m_Type == GraphObjectTypes::DefaultMaterial)
static_cast<SDefaultMaterial *>(&obj)->m_NextSibling = sibling;
else
diff --git a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
index 5d70931..ae46f49 100644
--- a/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
+++ b/src/runtimerender/Qt3DSRenderMaterialShaderGenerator.h
@@ -40,8 +40,12 @@ namespace qt3ds {
namespace render {
// these are our current shader limits
+#ifndef QT3DS_MAX_NUM_LIGHTS
#define QT3DS_MAX_NUM_LIGHTS 16
+#endif
+#ifndef QT3DS_MAX_NUM_SHADOWS
#define QT3DS_MAX_NUM_SHADOWS 8
+#endif
// note this struct must exactly match the memory layout of the
// struct sampleLight.glsllib and sampleArea.glsllib. If you make changes here you need
diff --git a/src/runtimerender/Qt3DSRenderShaderCache.cpp b/src/runtimerender/Qt3DSRenderShaderCache.cpp
index a71d3fd..15c1b45 100644
--- a/src/runtimerender/Qt3DSRenderShaderCache.cpp
+++ b/src/runtimerender/Qt3DSRenderShaderCache.cpp
@@ -126,6 +126,7 @@ struct ShaderCache : public IShaderCache
IInputStreamFactory &m_InputStreamFactory;
bool m_ShaderCompilationEnabled = true;
bool m_shadersInitializedFromCache = false;
+ bool m_binaryShaderCache = false;
volatile QT3DSI32 mRefCount = 0;
struct ShaderSource
@@ -291,23 +292,51 @@ struct ShaderCache : public IShaderCache
// add precision qualifier depending on backend
if (IQt3DSRenderer::IsGlEs3Context(m_RenderContext.GetRenderContextType())) {
- m_InsertStr.append("precision highp float;\n"
- "precision highp int;\n");
- if( m_RenderContext.GetRenderBackendCap(render::NVRenderBackend::NVRenderBackendCaps::gpuShader5) ) {
- m_InsertStr.append("precision mediump sampler2D;\n"
- "precision mediump sampler2DArray;\n"
- "precision mediump sampler2DShadow;\n");
+ QString precision = qEnvironmentVariable("QT3DS_PRECISION");
+ QString samplerPrecision = qEnvironmentVariable("QT3DS_SAMPLER_PRECISION");
+
+ if ((!precision.isEmpty() && precision != QStringLiteral("mediump")
+ && precision != QStringLiteral("lowp")
+ && precision != QStringLiteral("highp")) || precision.isEmpty()) {
+ precision = "highp";
+ }
+ if ((!samplerPrecision.isEmpty()
+ && samplerPrecision != QStringLiteral("mediump")
+ && samplerPrecision != QStringLiteral("lowp")
+ && samplerPrecision != QStringLiteral("highp"))
+ || samplerPrecision.isEmpty()) {
+ samplerPrecision = "mediump";
+ }
+
+ QString precisionQualifiers("precision %1 float;\n"
+ "precision %1 int;\n");
+ m_InsertStr.append(precisionQualifiers.arg(precision));
+ if (m_RenderContext.GetRenderBackendCap(
+ NVRenderBackend::NVRenderBackendCaps::gpuShader5)) {
+ QString samplerQualifiers("precision %1 sampler2D;\n"
+ "precision %1 sampler2DArray;\n"
+ "precision %1 sampler2DShadow;\n");
+ m_InsertStr.append(samplerQualifiers.arg(samplerPrecision));
if (m_RenderContext.IsShaderImageLoadStoreSupported()) {
- m_InsertStr.append("precision mediump image2D;\n");
+ QString imageQualifiers("precision %1 image2D;\n");
+ m_InsertStr.append(imageQualifiers.arg(samplerPrecision));
}
}
AddBackwardCompatibilityDefines(shaderType);
} else {
// GLES2
- m_InsertStr.append("precision mediump float;\n"
- "precision mediump int;\n"
- "#define texture texture2D\n");
+ QString precision = qEnvironmentVariable("QT3DS_PRECISION");
+ if ((!precision.isEmpty() && precision != QStringLiteral("mediump")
+ && precision != QStringLiteral("lowp")
+ && precision != QStringLiteral("highp")) || precision.isEmpty()) {
+ precision = "mediump";
+ }
+ QString precisionQualifiers("precision %1 float;\n"
+ "precision %1 int;\n");
+ m_InsertStr.append(precisionQualifiers.arg(precision));
+ m_InsertStr.append("#define texture texture2D\n");
+
if (m_RenderContext.IsTextureLodSupported())
m_InsertStr.append("#define textureLod texture2DLodEXT\n");
else
@@ -411,7 +440,7 @@ struct ShaderCache : public IShaderCache
if (!inFrag)
inFrag = "";
- QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "Shader Compilation")
+ QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "ShaderCache: Compilation")
m_VertexCode.assign(inVert);
m_TessCtrlCode.assign(inTessCtrl);
m_TessEvalCode.assign(inTessEval);
@@ -431,22 +460,22 @@ struct ShaderCache : public IShaderCache
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.
- // Unfortunately it is not practical to just regenerate shader source from scratch, when we
- // want to export it, as the triggers and original sources are spread all over the place.
- if (!m_shadersInitializedFromCache && theInserter.first->second) {
+ if (theInserter.first->second) {
// Store sources for possible cache generation later
ShaderSource ss;
for (QT3DSU32 i = 0, end = inFeatures.size(); i < end; ++i)
ss.features.append(inFeatures[i]);
ss.key = inKey;
ss.flags = inFlags;
- ss.vertexCode = inVert;
- ss.fragmentCode = inFrag;
- ss.tessCtrlCode = inTessCtrl;
- ss.tessEvalCode = inTessEval;
- ss.geometryCode = inGeom;
+ // Do not store shader sources for binary cache
+ if (!m_shadersInitializedFromCache
+ || (m_shadersInitializedFromCache && !m_binaryShaderCache)) {
+ ss.vertexCode = inVert;
+ ss.fragmentCode = inFrag;
+ ss.tessCtrlCode = inTessCtrl;
+ ss.tessEvalCode = inTessEval;
+ ss.geometryCode = inGeom;
+ }
m_shaderSourceCache.append(ss);
}
@@ -476,9 +505,13 @@ struct ShaderCache : public IShaderCache
QByteArray exportShaderCache(bool binaryShaders) override
{
if (m_shadersInitializedFromCache) {
- qWarning() << __FUNCTION__ << "Warning: Shader cache export is not supported when"
- " shaders were originally imported from a cache file.";
- return {};
+ if (m_binaryShaderCache != binaryShaders) {
+ qWarning() << __FUNCTION__ << "Warning: Shader cache export and"
+ " import mode mismatch.";
+ return {};
+ }
+ qWarning() << __FUNCTION__ << "Warning: Shader cache export while also imported"
+ " from the cache. This might not be intended.";
}
// The assumption is that cache was generated on the same environment it will be read.
@@ -543,17 +576,18 @@ struct ShaderCache : public IShaderCache
return retval;
}
- void importShaderCache(const QByteArray &shaderCache) override
+ void importShaderCache(const QByteArray &shaderCache, QString &errors) override
{
#define BAILOUT(details) { \
- qWarning() << "importShaderCache failed to import shader cache:" << details; \
+ errors = "importShaderCache failed to import shader cache: " details; \
+ qWarning() << errors; \
return; \
}
if (shaderCache.isEmpty())
BAILOUT("Shader cache Empty")
- QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "ShaderCache - Import")
+ QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "ShaderCache: Import")
QDataStream data(shaderCache);
quint32 type;
@@ -571,6 +605,8 @@ struct ShaderCache : public IShaderCache
#undef BAILOUT
+ m_binaryShaderCache = isBinary;
+
IStringTable &stringTable(m_RenderContext.GetStringTable());
int progCount;
@@ -606,9 +642,13 @@ struct ShaderCache : public IShaderCache
qCInfo(TRACE_INFO) << "Loading binary program from shader cache: '<" << key << ">'";
eastl::pair<TShaderMap::iterator, bool> theInserter = m_Shaders.insert(tempKey);
- theInserter.first->second
- = m_RenderContext.CompileBinary(theKey, format, binary).mShader;
- theShader = theInserter.first->second;
+ auto ret = m_RenderContext.CompileBinary(theKey, format, binary);
+ if (!ret.errors.isEmpty()) {
+ errors += ret.errors + "\n";
+ } else {
+ theInserter.first->second = ret.mShader;
+ theShader = ret.mShader;
+ }
} else {
QByteArray loadVertexData;
QByteArray loadFragmentData;
@@ -635,12 +675,17 @@ struct ShaderCache : public IShaderCache
qt3ds::foundation::toDataRef(
features.data(), static_cast<QT3DSU32>(features.size())),
error, false, true);
+ if (!error.isEmpty()) {
+ errors += error + "\n";
+ theShader = nullptr;
+ }
}
}
// If something doesn't save or load correctly, get the runtime to re-generate.
if (!theShader) {
qWarning() << __FUNCTION__ << "Failed to load a cached a shader:" << key;
m_Shaders.erase(theKey);
+ m_shadersInitializedFromCache = false;
}
}
}
diff --git a/src/runtimerender/Qt3DSRenderShaderCache.h b/src/runtimerender/Qt3DSRenderShaderCache.h
index d03bc65..35713bd 100644
--- a/src/runtimerender/Qt3DSRenderShaderCache.h
+++ b/src/runtimerender/Qt3DSRenderShaderCache.h
@@ -103,7 +103,7 @@ namespace render {
// source code is exported
virtual QByteArray exportShaderCache(bool binaryShaders) = 0;
// This call immediately blocks and attempts to load all shaders from the shaderCache
- virtual void importShaderCache(const QByteArray &shaderCache) = 0;
+ virtual void importShaderCache(const QByteArray &shaderCache, QString &errors) = 0;
// It is up to the caller to ensure that inFeatures contains unique keys.
// It is also up the the caller to ensure the keys are ordered in some way.
virtual NVRenderShaderProgram *
diff --git a/src/runtimerender/Qt3DSRenderSubpresentation.cpp b/src/runtimerender/Qt3DSRenderSubpresentation.cpp
index 64f08be..834d773 100644
--- a/src/runtimerender/Qt3DSRenderSubpresentation.cpp
+++ b/src/runtimerender/Qt3DSRenderSubpresentation.cpp
@@ -68,10 +68,7 @@ namespace render {
QT3DSVec2 /*inPresScale*/,
const SRenderInstanceId instanceId)
{
- NVRenderRect theViewportSize(m_RenderContext.GetRenderList().GetViewport());
- bool wasDirty = m_Presentation.m_Scene->PrepareForRender(
- QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
- m_RenderContext, instanceId);
+ bool wasDirty = m_Presentation.m_Scene->PrepareForRender(m_RenderContext, instanceId);
// Always transparent
return SOffscreenRenderFlags(true, wasDirty);
}
@@ -84,6 +81,7 @@ namespace render {
const SRenderInstanceId instanceId)
{
NVRenderRect theViewportSize(inRenderContext.GetViewport());
+ m_Presentation.m_Scene->m_IsSubPresentationScene = true;
m_Presentation.m_Scene->Render(
QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
m_RenderContext, inClearColorBuffer, instanceId);
@@ -99,6 +97,7 @@ namespace render {
Q_UNUSED(inEnvironment);
Q_UNUSED(inPresScale);
NVRenderRect theViewportSize(inRenderContext.GetViewport());
+ m_Presentation.m_Scene->m_IsSubPresentationScene = true;
m_Presentation.m_Scene->RenderWithClear(
QT3DSVec2((QT3DSF32)theViewportSize.m_Width, (QT3DSF32)theViewportSize.m_Height),
m_RenderContext, inClearBuffer, inClearColor, id);
diff --git a/src/runtimerender/Qt3DSRenderTextTextureCache.cpp b/src/runtimerender/Qt3DSRenderTextTextureCache.cpp
index 8edbeca..91a841a 100644
--- a/src/runtimerender/Qt3DSRenderTextTextureCache.cpp
+++ b/src/runtimerender/Qt3DSRenderTextTextureCache.cpp
@@ -37,32 +37,41 @@
#include "render/Qt3DSRenderContext.h"
#include "foundation/Qt3DSInvasiveLinkedList.h"
#include "foundation/Qt3DSPool.h"
+#include <functional> // for std::hash
using namespace qt3ds::render;
+// Copied from boost
+template <class T>
+inline void hashCombine(std::size_t &seed, const T &v)
+{
+ std::hash<T> hasher;
+ seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+}
+
namespace eastl {
template <>
struct hash<STextRenderInfo>
{
size_t operator()(const qt3ds::render::STextRenderInfo &inInfo) const
{
- size_t retval = hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Text.c_str()));
- retval = retval ^ hash<size_t>()(reinterpret_cast<size_t>(inInfo.m_Font.c_str()));
- retval = retval ^ hash<float>()(inInfo.m_FontSize);
- retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_HorizontalAlignment));
- retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_VerticalAlignment));
- retval = retval ^ hash<float>()(inInfo.m_Leading);
- retval = retval ^ hash<float>()(inInfo.m_Tracking);
- retval = retval ^ hash<bool>()(inInfo.m_DropShadow);
- retval = retval ^ hash<float>()(inInfo.m_DropShadowStrength);
- retval = retval ^ hash<float>()(inInfo.m_DropShadowOffsetX);
- retval = retval ^ hash<float>()(inInfo.m_DropShadowOffsetY);
- retval = retval ^ hash<float>()(inInfo.m_BoundingBox.x);
- retval = retval ^ hash<float>()(inInfo.m_BoundingBox.y);
- retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_Elide));
- retval = retval ^ hash<int>()(static_cast<int>(inInfo.m_WordWrap));
- retval = retval ^ hash<bool>()(inInfo.m_EnableAcceleratedFont);
- return retval;
+ size_t hashValue = 0;
+ hashCombine(hashValue, std::string(inInfo.m_Font.c_str()));
+ hashCombine(hashValue, std::string(inInfo.m_Text.c_str()));
+ hashCombine(hashValue, int(inInfo.m_Elide));
+ hashCombine(hashValue, inInfo.m_Leading);
+ hashCombine(hashValue, inInfo.m_FontSize);
+ hashCombine(hashValue, inInfo.m_Tracking);
+ hashCombine(hashValue, int(inInfo.m_WordWrap));
+ hashCombine(hashValue, inInfo.m_DropShadow);
+ hashCombine(hashValue, inInfo.m_BoundingBox.x);
+ hashCombine(hashValue, inInfo.m_BoundingBox.y);
+ hashCombine(hashValue, inInfo.m_DropShadowOffsetX);
+ hashCombine(hashValue, inInfo.m_DropShadowOffsetY);
+ hashCombine(hashValue, inInfo.m_DropShadowStrength);
+ hashCombine(hashValue, int(inInfo.m_VerticalAlignment));
+ hashCombine(hashValue, int(inInfo.m_HorizontalAlignment));
+ return hashValue;
}
};
}
@@ -81,20 +90,7 @@ struct STextRenderInfoAndHash
}
bool operator==(const STextRenderInfoAndHash &inOther) const
{
- return m_Info.m_Text == inOther.m_Info.m_Text && m_Info.m_Font == inOther.m_Info.m_Font
- && m_Info.m_FontSize == inOther.m_Info.m_FontSize
- && m_Info.m_HorizontalAlignment == inOther.m_Info.m_HorizontalAlignment
- && m_Info.m_VerticalAlignment == inOther.m_Info.m_VerticalAlignment
- && m_Info.m_Leading == inOther.m_Info.m_Leading
- && m_Info.m_Tracking == inOther.m_Info.m_Tracking
- && m_Info.m_DropShadow == inOther.m_Info.m_DropShadow
- && m_Info.m_DropShadowStrength == inOther.m_Info.m_DropShadowStrength
- && m_Info.m_DropShadowOffsetX == inOther.m_Info.m_DropShadowOffsetX
- && m_Info.m_DropShadowOffsetY == inOther.m_Info.m_DropShadowOffsetY
- && m_Info.m_BoundingBox == inOther.m_Info.m_BoundingBox
- && m_Info.m_WordWrap == inOther.m_Info.m_WordWrap
- && m_Info.m_EnableAcceleratedFont == inOther.m_Info.m_EnableAcceleratedFont
- && m_ScaleFactor == inOther.m_ScaleFactor;
+ return m_Hashcode == inOther.m_Hashcode;
}
};
}
@@ -189,7 +185,6 @@ struct STextTextureCache : public ITextTextureCache
STextCacheNode &theEnd = m_LRUList.back();
if (theEnd.m_FrameCount != m_FrameCount) {
nextTexture = theEnd.m_TextInfo.second.second;
- STextureDetails theDetails = nextTexture->GetTextureDetails();
m_TextureTotalBytes -= GetNumBytes(*nextTexture.mPtr);
m_LRUList.remove(theEnd);
// copy the key because the next statement will destroy memory
@@ -204,8 +199,7 @@ struct STextTextureCache : public ITextTextureCache
TTPathObjectAndTexture RenderText(const STextRenderInfo &inText, QT3DSF32 inScaleFactor) override
{
STextRenderInfoAndHash theKey(inText, inScaleFactor);
- TTextureInfoHash::iterator theFind(
- m_TextureCache.find(theKey));
+ TTextureInfoHash::iterator theFind(m_TextureCache.find(theKey));
STextCacheNode *retval = NULL;
if (theFind != m_TextureCache.end()) {
retval = theFind->second;
@@ -220,23 +214,11 @@ struct STextTextureCache : public ITextTextureCache
NVScopedRefCounted<NVRenderPathFontItem> nextPathFontItemObject;
NVScopedRefCounted<NVRenderPathFontSpecification> nextPathFontObject;
- // HW acceleration for fonts not supported
- //if (m_CanUsePathRendering && inText.m_EnableAcceleratedFont) {
- // nextPathFontItemObject = m_RenderContext->CreatePathFontItem();
- // nextPathFontObject = m_RenderContext->CreatePathFontSpecification(inText.m_Font);
- //}
STextRenderInfo theTextInfo(inText);
theTextInfo.m_FontSize *= inScaleFactor;
STextTextureDetails theDetails;
-
-
- // HW acceleration for fonts not supported
- //if (!m_CanUsePathRendering || !inText.m_EnableAcceleratedFont)
- theDetails = m_TextRenderer->RenderText(theTextInfo, *nextTexture.mPtr);
- //else
- // theDetails = m_TextRenderer->RenderText(theTextInfo, *nextPathFontItemObject.mPtr,
- // *nextPathFontObject.mPtr);
+ theDetails = m_TextRenderer->RenderText(theTextInfo, *nextTexture.mPtr);
if (fabs(inScaleFactor - 1.0f) > .001f) {
TTPathObjectAndTexture theCanonicalDetails = RenderText(inText, 1.0f);
diff --git a/src/runtimerender/Qt3DSRenderTextTypes.h b/src/runtimerender/Qt3DSRenderTextTypes.h
index bbaaa38..f663e50 100644
--- a/src/runtimerender/Qt3DSRenderTextTypes.h
+++ b/src/runtimerender/Qt3DSRenderTextTypes.h
@@ -182,8 +182,6 @@ namespace render {
QT3DSF32 m_ScaleX; // Pixel scale in X
QT3DSF32 m_ScaleY; // Pixel scale in Y
- bool m_EnableAcceleratedFont; // use NV path rendering
-
STextRenderInfo();
~STextRenderInfo();
};
diff --git a/src/runtimerender/Qt3DSRenderUIPLoader.cpp b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
index 24e4c18..932579b 100644
--- a/src/runtimerender/Qt3DSRenderUIPLoader.cpp
+++ b/src/runtimerender/Qt3DSRenderUIPLoader.cpp
@@ -108,6 +108,7 @@ using qt3ds::render::SDefaultMaterial;
using qt3ds::render::SImage;
using qt3ds::render::SGraphObject;
using qt3ds::render::SDynamicObject;
+using qt3ds::render::SDynamicGraphObject;
using qt3ds::render::SEffect;
using qt3ds::render::SCustomMaterial;
using qt3ds::render::GraphObjectTypes;
@@ -517,6 +518,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
MemoryBuffer<RawAllocator> m_ValueBuffer;
TIdPathAnchorIndexMap m_AnchorIdToPathAndAnchorIndexMap;
const Q3DSVariantConfig &m_variantConfig;
+ int m_uipVersion;
SRenderUIPLoader(qt3dsdm::IDOMReader &inReader, const char8_t *inFullPathToPresentationFile,
Q3DStudio::IRuntimeMetaData &inMetaData, IStringTable &inStrTable
@@ -534,7 +536,8 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
qt3ds::render::ICustomMaterialSystem &inCMS,
qt3ds::render::IDynamicObjectSystem &inDynamicSystem,
qt3ds::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver,
- const Q3DSVariantConfig &variantConfig)
+ const Q3DSVariantConfig &variantConfig,
+ int uipVersion)
: m_Reader(inReader)
, m_MetaData(inMetaData)
, m_StrTable(inStrTable)
@@ -552,6 +555,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
, m_PathManager(inPathManager)
, m_ReferenceResolver(inResolver)
, m_variantConfig(variantConfig)
+ , m_uipVersion(uipVersion)
{
std::string presentationFile = inFullPathToPresentationFile;
std::string::size_type pos = presentationFile.find_last_of("\\/");
@@ -716,6 +720,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Node_LocalOpacity "opacity"
#define Node_RotationOrder "rotationorder"
#define Node_LeftHanded "orientation"
+#define Group_ordered "ordered"
#define Layer_Variants "variants"
#define Layer_TemporalAAEnabled "temporalaa"
#define Layer_LayerEnableDepthTest "disabledepthtest"
@@ -726,6 +731,10 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Layer_Size "size"
#define Layer_Location "location"
#define Layer_TexturePath "sourcepath"
+#define Layer_DynamicResize "dynamicresize"
+#define Layer_DynamicPaddingUnits "dynamicpaddingunits"
+#define Layer_DynamicPadding "dynamicpadding"
+#define Layer_DynamicCombine "dynamiccombine"
#define Layer_HorizontalFieldValues "horzfields"
#define Layer_Left "left"
#define Layer_LeftUnits "leftunits"
@@ -740,6 +749,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Layer_HeightUnits "heightunits"
#define Layer_Bottom "bottom"
#define Layer_BottomUnits "bottomunits"
+#define Layer_AoEnabled "aoenabled"
#define Layer_AoStrength "aostrength"
#define Layer_AoDistance "aodistance"
#define Layer_AoSoftness "aosoftness"
@@ -824,6 +834,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Material_ReferencedMaterial "referencedmaterial"
#define Material_VertexColors "vertexcolors"
#define Material_TransparencyMode "transparencymode"
+#define Material_CullMode "cullmode"
#define Image_ImagePath "sourcepath"
#define Image_OffscreenRendererId "subpresentation"
#define Image_Scale_X "scaleu"
@@ -833,6 +844,8 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
#define Image_Rotation "rotationuv"
#define Image_Position_X "positionu"
#define Image_Position_Y "positionv"
+#define Image_MinFilter "minfilter"
+#define Image_MagFilter "magfilter"
#define Image_MappingMode "mappingmode"
#define Image_HorizontalTilingMode "tilingmodehorz"
#define Image_VerticalTilingMode "tilingmodevert"
@@ -928,6 +941,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
inItem.m_Flags.SetActive(eyeball);
ITERATE_QT3DS_RENDER_NODE_PROPERTIES
ParseProperty(inParser, "boneid", inItem.m_SkeletonId);
+ ParseProperty(inParser, "ordered", inItem.m_ordered);
bool ignoreParent = false;
if (ParseProperty(inParser, "ignoresparent", ignoreParent))
inItem.m_Flags.SetIgnoreParentTransform(ignoreParent);
@@ -997,7 +1011,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
const qt3ds::render::dynamic::SPropertyDefinition &inPropDesc,
const TDataType &inProp)
{
- memCopy(inEffect.GetDataSectionBegin() + inPropDesc.m_Offset, &inProp, sizeof(TDataType));
+ memCopy(inEffect.GetDataSectionOffset(inPropDesc.m_Offset), &inProp, sizeof(TDataType));
}
template <typename TDataType>
void SetDynamicObjectProperty(SDynamicObject &inEffect,
@@ -1010,29 +1024,30 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
}
void ParseProperties(SCustomMaterial &inItem, IPropertyParser &inParser)
{
- ParseProperties(static_cast<SDynamicObject &>(inItem), inParser);
+ ParseProperties(static_cast<SDynamicGraphObject &>(inItem), inParser);
ParseProperties(inItem.m_Lightmaps, inParser);
ITERATE_QT3DS_RENDER_CUSTOM_MATERIAL_PROPERTIES
}
- void ParseProperties(SDynamicObject &inDynamicObject, IPropertyParser &inParser)
+ void ParseProperties(SDynamicGraphObject &inDynamicObject, IPropertyParser &inParser)
{
NVConstDataRef<qt3ds::render::dynamic::SPropertyDefinition> theProperties =
m_DynamicObjectSystem.GetProperties(inDynamicObject.m_ClassName);
+ SDynamicObject &dynObj = *inDynamicObject.m_dynamicObject;
for (QT3DSU32 idx = 0, end = theProperties.size(); idx < end; ++idx) {
const qt3ds::render::dynamic::SPropertyDefinition &theDefinition(theProperties[idx]);
switch (theDefinition.m_DataType) {
case qt3ds::render::NVRenderShaderDataTypes::QT3DSRenderBool:
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseBool(theDefinition.m_Name));
break;
case qt3ds::render::NVRenderShaderDataTypes::QT3DSF32:
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseFloat(theDefinition.m_Name));
break;
case qt3ds::render::NVRenderShaderDataTypes::QT3DSI32:
if (theDefinition.m_IsEnumProperty == false)
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseU32(theDefinition.m_Name));
else {
Option<eastl::string> theEnum = inParser.ParseStr(theDefinition.m_Name);
@@ -1041,7 +1056,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
theDefinition.m_EnumValueNames;
for (QT3DSU32 idx = 0, end = theEnumNames.size(); idx < end; ++idx) {
if (theEnum->compare(theEnumNames[idx].c_str()) == 0) {
- SetDynamicObjectProperty(inDynamicObject, theDefinition, idx);
+ SetDynamicObjectProperty(dynObj, theDefinition, idx);
break;
}
}
@@ -1049,15 +1064,15 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
}
break;
case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec4:
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseVec4(theDefinition.m_Name));
break;
case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec3:
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseVec3(theDefinition.m_Name));
break;
case qt3ds::render::NVRenderShaderDataTypes::QT3DSVec2:
- SetDynamicObjectProperty(inDynamicObject, theDefinition,
+ SetDynamicObjectProperty(dynObj, theDefinition,
inParser.ParseVec2(theDefinition.m_Name));
break;
case qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr:
@@ -1067,8 +1082,28 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
CRegisteredString theStr;
if (theTexture->size())
theStr = m_StrTable.RegisterStr(theTexture->c_str());
-
- SetDynamicObjectProperty(inDynamicObject, theDefinition, theStr);
+ if (theStr.IsValid() && theStr.c_str()[0] == '#') {
+ CRegisteredString ref = m_StrTable.RegisterStr(theTexture->c_str() + 1);
+ SImage *image = nullptr;
+ auto result = m_ObjectMap.find(ref);
+ if (result != m_ObjectMap.end())
+ image = static_cast<SImage *>(result->second);
+ if (image)
+ inDynamicObject.setImage(theDefinition.m_Name, image);
+ SetDynamicObjectProperty(dynObj, theDefinition, theDefinition.m_Name);
+ } else if (this->m_uipVersion < 7) {
+ SImage *img = inDynamicObject.getImage(theDefinition.m_Name);
+ if (!img) {
+ img = QT3DS_NEW(m_PresentationAllocator, SImage);
+ img->m_HorizontalTilingMode = theDefinition.m_CoordOp;
+ img->m_VerticalTilingMode = theDefinition.m_CoordOp;
+ img->m_MagFilter = theDefinition.m_MagFilterOp;
+ img->m_MinFilter = theDefinition.m_MinFilterOp;
+ SetDynamicObjectProperty(dynObj, theDefinition, theDefinition.m_Name);
+ }
+ img->m_ImagePath = theStr;
+ inDynamicObject.setImage(theDefinition.m_Name, img);
+ }
}
} break;
case qt3ds::render::NVRenderShaderDataTypes::NVRenderDataBufferPtr:
@@ -1252,6 +1287,9 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
case qt3dsdm::ComposerObjectTypes::Group:
theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)();
break;
+ case qt3dsdm::ComposerObjectTypes::Signal:
+ theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)();
+ break;
case qt3dsdm::ComposerObjectTypes::Component:
theNewObject = QT3DS_NEW(m_PresentationAllocator, SNode)();
break;
@@ -1298,6 +1336,8 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
case qt3dsdm::ComposerObjectTypes::Effect: {
const char8_t *effectClassId;
m_Reader.Att("class", effectClassId);
+ if (!effectClassId)
+ break;
CRegisteredString theStr = m_StrTable.RegisterStr(effectClassId + 1);
if (m_EffectSystem.IsEffectRegistered(theStr))
theNewObject = m_EffectSystem.CreateEffectInstance(theStr, m_PresentationAllocator);
@@ -1326,6 +1366,8 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
case qt3dsdm::ComposerObjectTypes::CustomMaterial: {
const char8_t *materialClassId;
m_Reader.Att("class", materialClassId);
+ if (!materialClassId)
+ break;
CRegisteredString theStr = m_StrTable.RegisterStr(materialClassId + 1);
if (m_CustomMaterialSystem.IsMaterialRegistered(theStr)) {
theNewObject =
@@ -1377,6 +1419,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
QT3DS_ASSERT(false);
}
break;
+ case GraphObjectTypes::Effect:
case GraphObjectTypes::ReferencedMaterial:
if (theNewObject->m_Type == GraphObjectTypes::Image) {
// nothing to do yet
@@ -1699,6 +1742,7 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
QT3DS_ASSERT(success);
}
m_Reader.Att("preferKTX", m_Presentation->m_preferKTX);
+ m_Reader.Att("flipCompressedTextures", m_Presentation->m_flipCompressedTextures);
}
}
{
@@ -1832,7 +1876,10 @@ struct SRenderUIPLoader : public IDOMReferenceResolver
m_Reader.Att("hasTransparency", hasTransparency);
bool hasOpaque = false;
m_Reader.Att("hasOpaquePixels", hasOpaque);
- m_BufferManager.SetImageHasTransparency(imgPath, hasTransparency,
+ auto resolved = IBufferManager::resolveImagePath(
+ QString::fromLatin1(imgPath.c_str()),
+ m_Presentation->m_preferKTX);
+ m_BufferManager.SetImageHasTransparency(resolved, hasTransparency,
hasOpaque);
}
}
@@ -1898,12 +1945,12 @@ SPresentation *qt3ds::render::IUIPLoader::LoadUIPFile(
const char8_t *inPresentationDir, IRenderPluginManager &inPluginManager,
ICustomMaterialSystem &inCMS, IDynamicObjectSystem &inDynamicSystem,
qt3ds::render::IPathManager &inPathManager, IUIPReferenceResolver *inResolver,
- const Q3DSVariantConfig &variantConfig, bool inSetValuesFromSlides)
+ const Q3DSVariantConfig &variantConfig, bool inSetValuesFromSlides, int uipVersion)
{
SRenderUIPLoader theLoader(inReader, inFullPathToPresentationFile, inMetaData, inStrTable,
inFoundation, inPresentationAllocator, ioObjectMap, inBufferManager,
inEffectSystem, inPresentationDir, inPluginManager, inCMS,
- inDynamicSystem, inPathManager, inResolver, variantConfig);
+ inDynamicSystem, inPathManager, inResolver, variantConfig, uipVersion);
return theLoader.Load(inSetValuesFromSlides);
}
using namespace qt3dsdm;
diff --git a/src/runtimerender/Qt3DSRenderUIPLoader.h b/src/runtimerender/Qt3DSRenderUIPLoader.h
index 2b70c68..b07d0c3 100644
--- a/src/runtimerender/Qt3DSRenderUIPLoader.h
+++ b/src/runtimerender/Qt3DSRenderUIPLoader.h
@@ -113,7 +113,7 @@ namespace render {
// Useful for quick testing, sort of equivalent to showing the first frame
// of a given presentation
,
- bool setValuesFromSlides = false);
+ bool setValuesFromSlides, int uipVersion);
static void CreateEffectClassFromMetaEffect(CRegisteredString inEffectName,
NVFoundationBase &inFoundation,
diff --git a/src/runtimerender/Qt3DSRenderUIPSharedTranslation.cpp b/src/runtimerender/Qt3DSRenderUIPSharedTranslation.cpp
index 077a337..998de32 100644
--- a/src/runtimerender/Qt3DSRenderUIPSharedTranslation.cpp
+++ b/src/runtimerender/Qt3DSRenderUIPSharedTranslation.cpp
@@ -66,13 +66,11 @@ namespace render {
#define WCHAR_T_4x L"4x"
#define WCHAR_T_8x L"8x"
#define WCHAR_T_SSAA L"SSAA"
-#define WCHAR_T_NoRotation L"NoRotation"
#define WCHAR_T_Clockwise90 L"90"
#define WCHAR_T_Clockwise180 L"180"
#define WCHAR_T_Clockwise270 L"270"
#define WCHAR_T_Fit L"Fit"
#define WCHAR_T_Same_Size L"Same Size"
-#define WCHAR_T_CENTER L"Center"
#define WCHAR_T_North L"N"
#define WCHAR_T_NorthEast L"NE"
#define WCHAR_T_East L"E"
@@ -108,14 +106,19 @@ namespace render {
#define WCHAR_T_Filled L"Filled"
#define WCHAR_T_Stroked L"Stroked"
#define WCHAR_T_FilledAndStroked L"Filled and Stroked"
-#define WCHAR_T_Simple L"Simple"
-#define WCHAR_T_Smoke L"Smoke"
-#define WCHAR_T_Cloud L"Cloud"
-#define WCHAR_T_Fluid L"Fluid"
-#define WCHAR_T_User L"User"
#define WCHAR_T_Clip L"Clip"
#define WCHAR_T_WrapWord L"WrapWord"
#define WCHAR_T_WrapAnywhere L"WrapAnywhere"
+#define WCHAR_T_Back L"Back"
+#define WCHAR_T_Front L"Front"
+#define WCHAR_T_All L"All"
+#define WCHAR_T_None L"None"
+#define WCHAR_T_Nearest L"Nearest"
+#define WCHAR_T_Linear L"Linear"
+#define WCHAR_T_NearestMipmapNearest L"NearestMipmapNearest"
+#define WCHAR_T_LinearMipmapNearest L"LinearMipmapNearest"
+#define WCHAR_T_NearestMipmapLinear L"NearestMipmapLinear"
+#define WCHAR_T_LinearMipmapLinear L"LinearMipmapLinear"
#define CHAR_T_Directional "Directional"
#define CHAR_T_Point "Point"
@@ -151,13 +154,11 @@ namespace render {
#define CHAR_T_4x "4x"
#define CHAR_T_8x "8x"
#define CHAR_T_SSAA "SSAA"
-#define CHAR_T_NoRotation "NoRotation"
#define CHAR_T_Clockwise90 "90"
#define CHAR_T_Clockwise180 "180"
#define CHAR_T_Clockwise270 "270"
#define CHAR_T_Fit "Fit"
#define CHAR_T_Same_Size "Same Size"
-#define CHAR_T_CENTER "Center"
#define CHAR_T_North "N"
#define CHAR_T_NorthEast "NE"
#define CHAR_T_East "E"
@@ -193,14 +194,19 @@ namespace render {
#define CHAR_T_Filled "Filled"
#define CHAR_T_Stroked "Stroked"
#define CHAR_T_FilledAndStroked "Filled and Stroked"
-#define CHAR_T_Simple "Simple"
-#define CHAR_T_Smoke "Smoke"
-#define CHAR_T_Cloud "Cloud"
-#define CHAR_T_Fluid "Fluid"
-#define CHAR_T_User "User"
#define CHAR_T_Clip "Clip"
#define CHAR_T_WrapWord "WrapWord"
#define CHAR_T_WrapAnywhere "WrapAnywhere"
+#define CHAR_T_Back "Back"
+#define CHAR_T_Front "Front"
+#define CHAR_T_All "All"
+#define CHAR_T_None "None"
+#define CHAR_T_Nearest "Nearest"
+#define CHAR_T_Linear "Linear"
+#define CHAR_T_NearestMipmapNearest "NearestMipmapNearest"
+#define CHAR_T_LinearMipmapNearest "LinearMipmapNearest"
+#define CHAR_T_NearestMipmapLinear "NearestMipmapLinear"
+#define CHAR_T_LinearMipmapLinear "LinearMipmapLinear"
#define DEFINE_NAME_MAP_ENTRY(enumval, name) \
{ \
@@ -237,6 +243,14 @@ namespace render {
{ (QT3DSU32)-1, NULL },
};
+ SEnumNameMap g_CullModeMap[] = {
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialCullMode::Back, Back),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialCullMode::Front, Front),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialCullMode::FrontAndBack, All),
+ DEFINE_NAME_MAP_ENTRY(DefaultMaterialCullMode::None, None),
+ { (QT3DSU32)-1, NULL },
+ };
+
SEnumNameMap g_RenderTextureCoordOpMap[] = {
DEFINE_NAME_MAP_ENTRY(NVRenderTextureCoordOp::ClampToEdge, No_Tiling),
DEFINE_NAME_MAP_ENTRY(NVRenderTextureCoordOp::MirroredRepeat, Mirrored),
@@ -244,6 +258,22 @@ namespace render {
{ (QT3DSU32)-1, NULL },
};
+ SEnumNameMap g_RenderTextureMinifyingOpMap[] = {
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::Nearest, Nearest),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::Linear, Linear),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::NearestMipmapNearest, NearestMipmapNearest),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::LinearMipmapNearest, LinearMipmapNearest),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::NearestMipmapLinear, NearestMipmapLinear),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMinifyingOp::LinearMipmapLinear, LinearMipmapLinear),
+ { (QT3DSU32)-1, NULL },
+ };
+
+ SEnumNameMap g_RenderTextureMagnifyingOpMap[] = {
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMagnifyingOp::Nearest, Nearest),
+ DEFINE_NAME_MAP_ENTRY(NVRenderTextureMagnifyingOp::Linear, Linear),
+ { (QT3DSU32)-1, NULL },
+ };
+
SEnumNameMap g_TextHorizontalAlignmentMap[] = {
DEFINE_NAME_MAP_ENTRY(TextHorizontalAlignment::Left, Left),
DEFINE_NAME_MAP_ENTRY(TextHorizontalAlignment::Center, Center),
@@ -405,11 +435,23 @@ namespace render {
SEnumNameMap *SEnumParseMap<ImageMappingModes::Enum>::GetMap() { return g_ImageMappingModeMap; }
+ SEnumNameMap *SEnumParseMap<DefaultMaterialCullMode::Enum>::GetMap() { return g_CullModeMap; }
+
SEnumNameMap *SEnumParseMap<NVRenderTextureCoordOp::Enum>::GetMap()
{
return g_RenderTextureCoordOpMap;
}
+ SEnumNameMap *SEnumParseMap<NVRenderTextureMinifyingOp::Enum>::GetMap()
+ {
+ return g_RenderTextureMinifyingOpMap;
+ }
+
+ SEnumNameMap *SEnumParseMap<NVRenderTextureMagnifyingOp::Enum>::GetMap()
+ {
+ return g_RenderTextureMagnifyingOpMap;
+ }
+
SEnumNameMap *SEnumParseMap<TextHorizontalAlignment::Enum>::GetMap()
{
return g_TextHorizontalAlignmentMap;
diff --git a/src/runtimerender/Qt3DSRenderUIPSharedTranslation.h b/src/runtimerender/Qt3DSRenderUIPSharedTranslation.h
index 01740e6..e7c9c28 100644
--- a/src/runtimerender/Qt3DSRenderUIPSharedTranslation.h
+++ b/src/runtimerender/Qt3DSRenderUIPSharedTranslation.h
@@ -88,6 +88,18 @@ namespace render {
};
template <>
+ struct SEnumParseMap<NVRenderTextureMinifyingOp::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
+ struct SEnumParseMap<NVRenderTextureMagnifyingOp::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
+
+ template <>
struct SEnumParseMap<TextHorizontalAlignment::Enum>
{
static SEnumNameMap *GetMap();
@@ -197,6 +209,11 @@ namespace render {
{
static SEnumNameMap *GetMap();
};
+ template <>
+ struct SEnumParseMap<DefaultMaterialCullMode::Enum>
+ {
+ static SEnumNameMap *GetMap();
+ };
#define QT3DS_RENDER_WCHAR_T_XYZs L"XYZ"
#define QT3DS_RENDER_WCHAR_T_YZXs L"YZX"
@@ -308,7 +325,8 @@ namespace render {
HANDLE_QT3DS_RENDER_VEC3_PROPERTY(Node, Pivot, TransformDirty) \
HANDLE_QT3DS_RENDER_OPACITY_PROPERTY(Node, LocalOpacity, TransformDirty) \
HANDLE_QT3DS_ROTATION_ORDER_PROPERTY(Node, RotationOrder, TransformDirty) \
- HANDLE_QT3DS_NODE_ORIENTATION_PROPERTY(Node, LeftHanded, TransformDirty)
+ HANDLE_QT3DS_NODE_ORIENTATION_PROPERTY(Node, LeftHanded, TransformDirty) \
+ HANDLE_QT3DS_RENDER_PROPERTY(Group, ordered, Dirty)
#define ITERATE_QT3DS_RENDER_LAYER_PROPERTIES \
HANDLE_QT3DS_NODE_FLAGS_INVERSE_PROPERTY(Layer, LayerEnableDepthTest, Dirty) \
@@ -320,6 +338,10 @@ namespace render {
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, BlendType, Dirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, Background, Dirty) \
HANDLE_QT3DS_RENDER_SOURCEPATH_PROPERTY(Layer, TexturePath, Dirty) \
+ HANDLE_QT3DS_RENDER_PROPERTY(Layer, DynamicResize, Dirty) \
+ HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, DynamicPaddingUnits, Dirty) \
+ HANDLE_QT3DS_RENDER_PROPERTY(Layer, DynamicPadding, Dirty) \
+ HANDLE_QT3DS_RENDER_PROPERTY(Layer, DynamicCombine, Dirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, HorizontalFieldValues, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Layer, Left, Dirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, LeftUnits, Dirty) \
@@ -334,6 +356,7 @@ namespace render {
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, HeightUnits, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Layer, Bottom, Dirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Layer, BottomUnits, Dirty) \
+ HANDLE_QT3DS_RENDER_PROPERTY(Layer, AoEnabled, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Layer, AoStrength, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Layer, AoDistance, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Layer, AoSoftness, Dirty) \
@@ -434,7 +457,8 @@ namespace render {
HANDLE_QT3DS_RENDER_PROPERTY(Material, DisplaceAmount, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Material, TranslucencyMap, Dirty) \
HANDLE_QT3DS_RENDER_PROPERTY(Material, TranslucentFalloff, Dirty) \
- HANDLE_QT3DS_RENDER_PROPERTY(Material, DiffuseLightWrap, Dirty)
+ HANDLE_QT3DS_RENDER_PROPERTY(Material, DiffuseLightWrap, Dirty) \
+ HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Material, CullMode, Dirty)
#define ITERATE_QT3DS_RENDER_REFERENCED_MATERIAL_PROPERTIES \
HANDLE_QT3DS_RENDER_PROPERTY(Material, ReferencedMaterial, Dirty)
@@ -448,7 +472,9 @@ namespace render {
HANDLE_QT3DS_RENDER_VEC2_PROPERTY(Image, Position, TransformDirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, MappingMode, Dirty) \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, HorizontalTilingMode, Dirty) \
- HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, VerticalTilingMode, Dirty)
+ HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, VerticalTilingMode, Dirty) \
+ HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, MinFilter, Dirty) \
+ HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Image, MagFilter, Dirty)
#define ITERATE_QT3DS_RENDER_TEXT_PROPERTIES \
HANDLE_QT3DS_RENDER_PROPERTY(Text, Text, TextDirty) \
@@ -467,7 +493,6 @@ namespace render {
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Text, Elide, TextDirty) \
HANDLE_QT3DS_RENDER_COLOR_VEC3_PROPERTY(Text, TextColor, Dirty) \
HANDLE_QT3DS_RENDER_COLOR_PROPERTY(Text, TextColor, Dirty) \
- HANDLE_QT3DS_RENDER_PROPERTY(Text, EnableAcceleratedFont, Dirty)
#define ITERATE_QT3DS_RENDER_PATH_PROPERTIES \
HANDLE_QT3DS_RENDER_ENUM_PROPERTY(Path, PathType, Dirty) \
diff --git a/src/runtimerender/Qt3DSRenderer.h b/src/runtimerender/Qt3DSRenderer.h
index 2e6e6aa..383267c 100644
--- a/src/runtimerender/Qt3DSRenderer.h
+++ b/src/runtimerender/Qt3DSRenderer.h
@@ -40,6 +40,7 @@
#include "Qt3DSRenderCamera.h"
#include "render/Qt3DSRenderBaseTypes.h"
#include "Qt3DSRenderRay.h"
+#include <QtGui/qopengl.h>
namespace qt3ds {
namespace render {
@@ -131,7 +132,7 @@ namespace render {
virtual void RenderPointsIndirect() = 0;
// Returns true if this layer or a sibling was dirty.
- virtual bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
+ virtual bool PrepareLayerForRender(SLayer &inLayer,
bool inRenderSiblings = true,
const SRenderInstanceId id = nullptr) = 0;
virtual void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions, bool clear,
@@ -169,7 +170,11 @@ namespace render {
const QT3DSVec3 &inMouseVec) const = 0;
virtual QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const = 0;
- virtual uint getLayerTextureId(SLayer &layer) = 0;
+ virtual uint getLayerTextureId(SLayer &layer, const SRenderInstanceId id = nullptr) = 0;
+
+ virtual GLenum getTextureGlFormat(NVRenderTextureFormats::Enum internalFormat) = 0;
+
+ virtual STextureDetails getLayerTextureDetails(SLayer &layer, const SRenderInstanceId id = nullptr) = 0;
// Roughly equivalent of gluPickMatrix, allows users to setup a perspective transform that
// will draw some sub component
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h b/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h
index 7c6b10e..188672c 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderCustomMaterial.h
@@ -58,15 +58,14 @@ namespace render {
typedef NVFlags<SCustomMaterialShaderKeyValues::Enum, QT3DSU32> SCustomMaterialShaderKeyFlags;
- struct SCustomMaterial : public SDynamicObject
+ struct SCustomMaterial : public SDynamicGraphObject
{
- private:
- // These objects are only created via the dynamic object system.
- SCustomMaterial(const SCustomMaterial &);
- SCustomMaterial &operator=(const SCustomMaterial &);
- SCustomMaterial();
-
public:
+ SCustomMaterial(SDynamicObject *dynamicObject)
+ : SDynamicGraphObject(GraphObjectTypes::CustomMaterial, dynamicObject)
+ {
+ }
+
// lightmap section
SLightmaps m_Lightmaps;
// material section
@@ -78,10 +77,7 @@ namespace render {
SImage *m_DisplacementMap;
QT3DSF32 m_DisplaceAmount; ///< depends on the object size
- typedef qt3ds::foundation::nvhash_map<CRegisteredString, SImage *> TImageMapHash;
- TImageMapHash *m_imageMaps;
-
- SGraphObject *m_NextSibling;
+ SGraphObject *m_MaterialSibling;
SCustomMaterialShaderKeyFlags m_ShaderKeyValues; ///< input from MDL files
QT3DSU32 m_LayerCount; ///< input from MDL files
@@ -96,7 +92,7 @@ namespace render {
m_hasTransparency = false;
m_hasRefraction = false;
m_hasVolumetricDF = false;
- m_NextSibling = NULL;
+ m_MaterialSibling = NULL;
m_DirtyFlagWithInFrame = m_Flags.IsDirty();
m_IblProbe = NULL;
m_EmissiveMap2 = NULL;
@@ -104,7 +100,6 @@ namespace render {
m_DisplaceAmount = 0.0;
m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)inKey;
m_LayerCount = inLayerCount;
- m_imageMaps = nullptr;
m_error = CRegisteredString();
}
@@ -143,10 +138,10 @@ namespace render {
template <typename TRemapperType>
void Remap(TRemapperType &inRemapper)
{
- SDynamicObject::Remap(inRemapper);
+ SDynamicGraphObject::Remap(inRemapper);
m_Lightmaps.Remap(inRemapper);
inRemapper.Remap(m_IblProbe);
- inRemapper.RemapMaterial(m_NextSibling);
+ inRemapper.RemapMaterial(m_MaterialSibling);
inRemapper.Remap(m_EmissiveMap2);
inRemapper.Remap(m_DisplacementMap);
}
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp b/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp
index b914a5b..184d61d 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.cpp
@@ -62,6 +62,7 @@ SDefaultMaterial::SDefaultMaterial()
, m_DiffuseLightWrap(0.f)
, m_VertexColors(false)
, m_TransparencyMode(DefaultMaterialTransparencyMode::Default)
+ , m_CullMode(DefaultMaterialCullMode::Back)
, m_NextSibling(NULL)
, m_Parent(NULL)
{
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h b/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h
index 22af262..39015fe 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderDefaultMaterial.h
@@ -78,6 +78,16 @@ namespace render {
};
};
+ struct DefaultMaterialCullMode
+ {
+ enum Enum {
+ Back = 0,
+ Front,
+ FrontAndBack,
+ None
+ };
+ };
+
struct SImage;
struct QT3DS_AUTOTEST_EXPORT SDefaultMaterial : SGraphObject
@@ -116,6 +126,7 @@ namespace render {
QT3DSF32 m_DiffuseLightWrap; // 0 - 1
bool m_VertexColors;
DefaultMaterialTransparencyMode::Enum m_TransparencyMode;
+ DefaultMaterialCullMode::Enum m_CullMode;
// Materials are stored as a linked list on models.
SGraphObject *m_NextSibling;
SModel *m_Parent;
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
index 086453c..0dede4b 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
@@ -39,12 +39,10 @@ using namespace qt3ds;
using namespace qt3ds::render;
using namespace qt3ds::foundation;
-SDynamicObject::SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inObjName,
- QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize)
- : SGraphObject(inType)
- , m_ClassName(inObjName)
+SDynamicObject::SDynamicObject(CRegisteredString inObjName,
+ QT3DSU32 inDSByteSize)
+ : m_ClassName(inObjName)
, m_DataSectionByteSize(inDSByteSize)
- , m_ThisObjectSize(thisObjSize)
{
}
@@ -56,7 +54,7 @@ void SDynamicObject::SetPropertyValueT(const dynamic::SPropertyDefinition &inDef
QT3DS_ASSERT(false);
return;
}
- memCopy(GetDataSectionBegin() + inDefinition.m_Offset, &inValue, sizeof(inValue));
+ memCopy(GetDataSectionOffset(inDefinition.m_Offset), &inValue, sizeof(inValue));
}
void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
@@ -77,7 +75,7 @@ void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefi
QT3DS_ASSERT(false);
return;
}
- memCopy(GetDataSectionBegin() + inDefinition.m_Offset + inOffset, &inValue, sizeof(inValue));
+ memCopy(GetDataSectionOffset(inDefinition.m_Offset + inOffset), &inValue, sizeof(inValue));
}
void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefinition,
const QT3DSVec2 &inValue)
@@ -125,8 +123,26 @@ void SDynamicObject::SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefini
if (inProjectDir == NULL)
inProjectDir = "";
if (CFileTools::RequiresCombineBaseAndRelative(inValue)) {
- QString absolute = QDir(inProjectDir).filePath(inValue);
- ioWorkspace.assign(absolute.toLatin1().constData());
+ QString value(QDir::cleanPath(inValue));
+ QString projectDir(inProjectDir);
+ QString path = value;
+
+ bool tryResolveRelativePath = !projectDir.startsWith(QStringLiteral(":/"));
+ if (tryResolveRelativePath)
+ path.prepend(projectDir + QChar('/'));
+
+ if (tryResolveRelativePath) {
+ bool exists = QFileInfo(path).exists();
+ if (!exists && value.startsWith("../")) {
+ QString tryPath = projectDir + QChar('/') + value.right(value.size() - 3);
+ exists = QFileInfo(tryPath).exists();
+ if (exists)
+ path = tryPath;
+ else
+ path = value; // reset back to initial value if resolve failed
+ }
+ }
+ ioWorkspace.assign(path.toLatin1().constData());
SetPropertyValueT(inDefinition, inStrTable.RegisterStr(ioWorkspace.c_str()));
// We also adjust the image path in the definition
// I could not find a better place
@@ -161,3 +177,22 @@ void SDynamicObject::SetPropertyValue(const dynamic::SPropertyDefinition &inDefi
SetStrPropertyValueT(const_cast<dynamic::SPropertyDefinition &>(inDefinition), inValue,
inProjectDir, ioWorkspace, inStrTable);
}
+
+SDynamicGraphObject::SDynamicGraphObject(GraphObjectTypes::Enum inType,
+ SDynamicObject *dynamicObject)
+ : SGraphObject(inType), m_dynamicObject(dynamicObject), m_ClassName(m_dynamicObject->m_ClassName)
+{
+
+}
+
+void SDynamicGraphObject::setImage(CRegisteredString propertyName, SImage *image)
+{
+ m_images.insert(propertyName, image);
+}
+
+SImage *SDynamicGraphObject::getImage(CRegisteredString propertyName)
+{
+ if (m_images.contains(propertyName))
+ return m_images.value(propertyName);
+ return nullptr;
+}
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h
index 92ab3b2..7211a15 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.h
@@ -33,6 +33,7 @@
#include "Qt3DSRender.h"
#include "Qt3DSRenderGraphObject.h"
#include "Qt3DSRenderNode.h"
+#include "Qt3DSRenderImage.h"
#include "EASTL/string.h"
#include "StringTools.h"
@@ -44,20 +45,18 @@ namespace render {
}
// Dynamic objects are objects that have variable number of properties during runtime.
- struct SDynamicObject : public SGraphObject
+ struct SDynamicObject
{
CRegisteredString m_ClassName;
- NodeFlags m_Flags;
QT3DSU32 m_DataSectionByteSize;
- QT3DSU32 m_ThisObjectSize;
- SDynamicObject(GraphObjectTypes::Enum inType, CRegisteredString inClassName,
- QT3DSU32 inDSByteSize, QT3DSU32 thisObjSize);
+ SDynamicObject(CRegisteredString inClassName,
+ QT3DSU32 inDSByteSize);
QT3DSU8 *GetDataSectionBegin()
{
QT3DSU8 *thisObjectStart = reinterpret_cast<QT3DSU8 *>(this);
- QT3DSU8 *retval = thisObjectStart + m_ThisObjectSize;
+ QT3DSU8 *retval = thisObjectStart + sizeof(SDynamicObject);
QT3DS_ASSERT((reinterpret_cast<size_t>(retval) % 4 == 0));
return retval;
}
@@ -67,6 +66,16 @@ namespace render {
return const_cast<SDynamicObject *>(this)->GetDataSectionBegin();
}
+ QT3DSU8 *GetDataSectionOffset(QT3DSU32 offset)
+ {
+ return GetDataSectionBegin() + offset;
+ }
+
+ const QT3DSU8 *GetDataSectionOffset(QT3DSU32 offset) const
+ {
+ return const_cast<SDynamicObject *>(this)->GetDataSectionBegin() + offset;
+ }
+
QT3DSU8 *GetDataSectionEnd() { return GetDataSectionBegin() + m_DataSectionByteSize; }
template <typename TDataType>
@@ -104,10 +113,31 @@ namespace render {
template <typename TRemapperType>
void Remap(TRemapperType &inRemapper)
{
- SGraphObject::Remap(inRemapper);
inRemapper.Remap(m_ClassName);
}
};
+
+ struct SDynamicGraphObject : public SGraphObject
+ {
+ SDynamicObject *m_dynamicObject = nullptr;
+ CRegisteredString m_ClassName;
+ NodeFlags m_Flags;
+ QMap<CRegisteredString, SImage *> m_images;
+
+ SDynamicGraphObject(GraphObjectTypes::Enum inType, SDynamicObject *dynamicObject);
+
+ SImage *getImage(CRegisteredString propertyName);
+ void setImage(CRegisteredString propertyName, SImage *image);
+
+ // Generic method used during serialization
+ // to remap string and object pointers
+ template <typename TRemapperType>
+ void Remap(TRemapperType &inRemapper)
+ {
+ SGraphObject::Remap(inRemapper);
+ inRemapper.RemapDynamicObject(m_Type, m_dynamicObject);
+ }
+ };
}
}
#endif
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp b/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp
index 325073d..2f336c7 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderEffect.cpp
@@ -41,7 +41,6 @@ void SEffect::Initialize()
m_Layer = NULL;
m_NextEffect = NULL;
m_Context = NULL;
- m_imageMaps = nullptr;
m_error = CRegisteredString();
}
@@ -53,7 +52,7 @@ void SEffect::SetActive(bool inActive, IEffectSystem &inManager)
inManager.ResetEffectFrameData(*m_Context);
m_Flags.SetDirty(true);
if (inActive)
- inManager.SetEffectRequiresCompilation(m_ClassName, true);
+ inManager.SetEffectRequiresCompilation(m_dynamicObject->m_ClassName, true);
}
}
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderEffect.h b/src/runtimerender/graphobjects/Qt3DSRenderEffect.h
index e0db3d9..82e75db 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderEffect.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderEffect.h
@@ -47,15 +47,14 @@ namespace render {
// them and they have completely variable properties.
// see IEffectManager in order to create these effects.
// The data for the effect immediately follows the effect
- struct SEffect : public SDynamicObject
+ struct SEffect : public SDynamicGraphObject
{
- private:
- // These objects are only created via the dynamic object system.
- SEffect(const SEffect &);
- SEffect &operator=(const SEffect &);
- SEffect();
-
public:
+ SEffect(SDynamicObject *dynamicObject)
+ : SDynamicGraphObject(GraphObjectTypes::Effect, dynamicObject)
+ {
+ }
+
SLayer *m_Layer;
SEffect *m_NextEffect;
// Opaque pointer to context type implemented by the effect system.
@@ -63,9 +62,6 @@ namespace render {
// the first time it needs to render this effect.
SEffectContext *m_Context;
- typedef qt3ds::foundation::nvhash_map<CRegisteredString, SImage *> TImageMapHash;
- TImageMapHash *m_imageMaps;
-
CRegisteredString m_error;
void Initialize();
@@ -84,7 +80,7 @@ namespace render {
template <typename TRemapperType>
void Remap(TRemapperType &inRemapper)
{
- SDynamicObject::Remap(inRemapper);
+ SDynamicGraphObject::Remap(inRemapper);
inRemapper.Remap(m_Layer);
inRemapper.Remap(m_NextEffect);
inRemapper.NullPtr(m_Context);
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
index 1910d70..8b187f8 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderImage.cpp
@@ -48,6 +48,8 @@ SImage::SImage()
, m_MappingMode(ImageMappingModes::Normal)
, m_HorizontalTilingMode(NVRenderTextureCoordOp::ClampToEdge)
, m_VerticalTilingMode(NVRenderTextureCoordOp::ClampToEdge)
+ , m_MinFilter(NVRenderTextureMinifyingOp::Linear)
+ , m_MagFilter(NVRenderTextureMagnifyingOp::Linear)
{
m_Flags.SetActive(true);
m_Flags.SetDirty(true);
@@ -63,11 +65,13 @@ static void HandleOffscreenResult(SImage &theImage, SImageTextureData &newImage,
newImage.m_TextureFlags.SetPreMultiplied(theResult.m_HasTransparency);
wasDirty = wasDirty || theResult.m_HasChangedSinceLastFrame;
theImage.m_LastFrameOffscreenRenderer = theResult.m_Renderer;
- replaceTexture = true;
+ if (theImage.m_TextureData.m_Texture != theResult.m_Texture)
+ replaceTexture = true;
}
bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
- IRenderPluginManager &inPluginManager, bool forIbl)
+ IRenderPluginManager &inPluginManager, bool preferKtx, bool forIbl,
+ bool flipCompressed)
{
bool wasDirty = m_Flags.IsDirty();
@@ -81,6 +85,10 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
inRenderManager.MaybeRegisterOffscreenRenderer(theInstance, *theInstance);
SOffscreenRenderResult theResult = inRenderManager.GetRenderedItem(theInstance);
HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty);
+ inBufferManager.checkAlwaysPremultiplied(QString::fromLatin1(m_ImagePath.c_str()),
+ newImage.m_TextureFlags);
+ if (newImage.m_Texture && m_MinFilter > NVRenderTextureMinifyingOp::Linear && wasDirty)
+ newImage.m_Texture->GenerateMipmaps();
}
}
@@ -90,20 +98,29 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
SOffscreenRenderResult theResult =
inRenderManager.GetRenderedItem(m_OffscreenRendererId);
HandleOffscreenResult(*this, newImage, theResult, replaceTexture, wasDirty);
+ inBufferManager.checkAlwaysPremultiplied(QString::fromLatin1(m_ImagePath.c_str()),
+ newImage.m_TextureFlags);
+ if (newImage.m_Texture && m_MinFilter > NVRenderTextureMinifyingOp::Linear && wasDirty)
+ newImage.m_Texture->GenerateMipmaps();
+ } else if (!wasDirty) {
+ // Do not recheck image path if we are not dirty and we already have a texture
+ newImage.m_Texture = m_TextureData.m_Texture;
}
}
if (newImage.m_Texture == nullptr) {
m_LastFrameOffscreenRenderer = nullptr;
- if (m_ImagePath.IsValid() && !m_OffscreenRendererId.IsValid()) {
+ if (m_ImagePath.IsValid() && !m_OffscreenRendererId.IsValid()
+ && !inRenderManager.HasOffscreenRenderer(m_ImagePath)) {
// Image has sourcepath set
- if (!m_LoadedTextureData
- || m_LoadedTextureData->m_path != QString::fromUtf8(m_ImagePath.c_str())) {
+ const QString resolvedPath = IBufferManager::resolveImagePath(
+ QString::fromUtf8(m_ImagePath.c_str()), preferKtx);
+ if (!m_LoadedTextureData || m_LoadedTextureData->m_path != resolvedPath) {
if (m_LoadedTextureData)
m_LoadedTextureData->m_callbacks.removeOne(this);
forIbl = forIbl || m_MappingMode == ImageMappingModes::LightProbe;
- m_LoadedTextureData = inBufferManager.CreateReloadableImage(m_ImagePath, false,
- forIbl);
+ m_LoadedTextureData = inBufferManager.CreateReloadableImage(resolvedPath, false,
+ forIbl, flipCompressed);
m_LoadedTextureData->m_callbacks.push_back(this);
}
if (m_LoadedTextureData) {
@@ -111,6 +128,13 @@ bool SImage::ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager
newImage.m_Texture = m_LoadedTextureData->m_Texture;
newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags;
newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap;
+ } else if (m_Flags.IsForceLoad()) {
+ QSet<QString> ls;
+ ls.insert(resolvedPath);
+ inBufferManager.loadSet(ls, flipCompressed);
+ newImage.m_Texture = m_LoadedTextureData->m_Texture;
+ newImage.m_TextureFlags = m_LoadedTextureData->m_TextureFlags;
+ newImage.m_BSDFMipMap = m_LoadedTextureData->m_BSDFMipMap;
}
replaceTexture = m_TextureData.m_Texture != newImage.m_Texture;
}
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderImage.h b/src/runtimerender/graphobjects/Qt3DSRenderImage.h
index 9b71d3f..16cd02c 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderImage.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderImage.h
@@ -78,6 +78,8 @@ namespace render {
ImageMappingModes::Enum m_MappingMode;
NVRenderTextureCoordOp::Enum m_HorizontalTilingMode;
NVRenderTextureCoordOp::Enum m_VerticalTilingMode;
+ NVRenderTextureMinifyingOp::Enum m_MinFilter;
+ NVRenderTextureMagnifyingOp::Enum m_MagFilter;
// Setting any of the above variables means this object is dirty.
// Setting any of the vec2 properties means this object's transform is dirty
@@ -89,7 +91,8 @@ namespace render {
// Or finds the image.
// and sets up the texture transform
bool ClearDirty(IBufferManager &inBufferManager, IOffscreenRenderManager &inRenderManager,
- IRenderPluginManager &pluginManager, bool forIbl = false);
+ IRenderPluginManager &pluginManager, bool preferKtx, bool forIbl,
+ bool flipCompressed);
void CalculateTextureTransform();
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderLayer.cpp b/src/runtimerender/graphobjects/Qt3DSRenderLayer.cpp
index 36a826c..73957e8 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderLayer.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderLayer.cpp
@@ -43,6 +43,10 @@ SLayer::SLayer()
, m_Background(LayerBackground::Transparent)
, m_ClearColor(0.0f)
, m_BlendType(LayerBlendTypes::Normal)
+ , m_DynamicResize(false)
+ , m_DynamicPadding(0)
+ , m_DynamicPaddingUnits(LayerUnitTypes::Percent)
+ , m_DynamicCombine(false)
, m_HorizontalFieldValues(HorizontalFieldValues::LeftWidth)
, m_Left(0)
, m_LeftUnits(LayerUnitTypes::Percent)
@@ -57,6 +61,7 @@ SLayer::SLayer()
, m_HeightUnits(LayerUnitTypes::Percent)
, m_Bottom(0)
, m_BottomUnits(LayerUnitTypes::Percent)
+ , m_AoEnabled(false)
, m_AoStrength(0)
, m_AoDistance(5.0f)
, m_AoSoftness(50.0f)
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderLayer.h b/src/runtimerender/graphobjects/Qt3DSRenderLayer.h
index 5c08e91..df1523d 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderLayer.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderLayer.h
@@ -129,6 +129,11 @@ namespace render {
LayerBlendTypes::Enum m_BlendType;
+ bool m_DynamicResize;
+ QT3DSF32 m_DynamicPadding;
+ LayerUnitTypes::Enum m_DynamicPaddingUnits;
+ bool m_DynamicCombine;
+
HorizontalFieldValues::Enum m_HorizontalFieldValues;
QT3DSF32 m_Left;
LayerUnitTypes::Enum m_LeftUnits;
@@ -146,6 +151,7 @@ namespace render {
LayerUnitTypes::Enum m_BottomUnits;
// Ambient occlusion
+ bool m_AoEnabled;
QT3DSF32 m_AoStrength;
QT3DSF32 m_AoDistance;
QT3DSF32 m_AoSoftness;
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp b/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
index bf47bb8..b3e557f 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderNode.cpp
@@ -47,11 +47,13 @@ SNode::SNode(GraphObjectTypes::Enum inGraphObjectType)
, m_LocalOpacity(1.0f)
, m_GlobalOpacity(1.0f)
, m_SkeletonId(-1)
+ , m_ordered(false)
, m_Parent(NULL)
, m_NextSibling(NULL)
, m_PreviousSibling(NULL)
, m_FirstChild(NULL)
, m_DFSIndex(0)
+ , m_GroupIndex(0)
{
m_Flags.SetDirty(true);
m_Flags.SetTransformDirty(true);
@@ -72,11 +74,13 @@ SNode::SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator)
, m_GlobalTransform(inCloningObject.m_GlobalTransform)
, m_GlobalOpacity(inCloningObject.m_GlobalOpacity)
, m_SkeletonId(inCloningObject.m_SkeletonId)
+ , m_ordered(inCloningObject.m_ordered)
, m_Parent(NULL)
, m_NextSibling(NULL)
, m_PreviousSibling(NULL)
, m_FirstChild(NULL)
, m_DFSIndex(0)
+ , m_GroupIndex(0)
{
m_Flags.SetDirty(true);
m_Flags.SetTransformDirty(true);
@@ -430,7 +434,7 @@ NVBounds3 SNode::GetChildBounds(IBufferManager &inManager, IPathManager &inPathM
NVBounds3 retval;
retval.setEmpty();
for (SNode *child = m_FirstChild; child != NULL; child = child->m_NextSibling) {
- if (inChildFilter == NULL || inChildFilter->IncludeNode(*child)) {
+ if (inChildFilter == nullptr || inChildFilter->IncludeNode(*child)) {
NVBounds3 childBounds;
if (child->m_Flags.IsTransformDirty())
child->CalculateLocalTransform();
@@ -445,6 +449,96 @@ NVBounds3 SNode::GetChildBounds(IBufferManager &inManager, IPathManager &inPathM
return retval;
}
+NVBounds3 SNode::GetActiveBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ bool inIncludeChildren,
+ IQt3DSRenderNodeFilter *inChildFilter) const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ if (inIncludeChildren)
+ retval = GetActiveChildBounds(inManager, inPathManager, inChildFilter);
+
+ if (m_Type == GraphObjectTypes::Model)
+ retval.include(static_cast<const SModel *>(this)->GetModelBounds(inManager));
+ else if (m_Type == GraphObjectTypes::Text)
+ retval.include(static_cast<const SText *>(this)->GetTextBounds());
+ else if (m_Type == GraphObjectTypes::Path)
+ retval.include(inPathManager.GetBounds(*static_cast<const SPath *>(this)));
+ return retval;
+}
+
+NVBounds3 SNode::GetActiveChildBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ IQt3DSRenderNodeFilter *inChildFilter) const
+{
+ NVBounds3 retval;
+ retval.setEmpty();
+ for (SNode *child = m_FirstChild; child != nullptr; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()
+ && (inChildFilter == nullptr || inChildFilter->IncludeNode(*child))) {
+ NVBounds3 childBounds;
+ if (child->m_Flags.IsTransformDirty())
+ child->CalculateLocalTransform();
+ childBounds = child->GetActiveBounds(inManager, inPathManager);
+ if (childBounds.isEmpty() == false) {
+ // Transform the bounds into our local space.
+ childBounds.transform(child->m_LocalTransform);
+ retval.include(childBounds);
+ }
+ }
+ }
+ return retval;
+}
+
+void SNode::GetActiveBoundsList(QVector<QT3DSVec3> &points, IBufferManager &inManager,
+ IPathManager &inPathManager,
+ QT3DSMat44 localTransform,
+ bool inIncludeChildren,
+ IQt3DSRenderNodeFilter *inChildFilter) const
+{
+ if (inIncludeChildren)
+ GetActiveChildBoundsList(points, inManager, inPathManager, localTransform, inChildFilter);
+
+ NVBounds3 bounds;
+ bounds.setEmpty();
+ if (m_Type == GraphObjectTypes::Model)
+ bounds = static_cast<const SModel *>(this)->GetModelBounds(inManager);
+ else if (m_Type == GraphObjectTypes::Text)
+ bounds = static_cast<const SText *>(this)->GetTextBounds();
+ else if (m_Type == GraphObjectTypes::Path)
+ bounds = inPathManager.GetBounds(*static_cast<const SPath *>(this));
+ if (!bounds.isEmpty()) {
+ QT3DSVec3 newPoints[8];
+ newPoints[0] = bounds.minimum;
+ newPoints[1] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.minimum.z);
+ newPoints[2] = QT3DSVec3(bounds.maximum.x, bounds.maximum.y, bounds.minimum.z);
+ newPoints[3] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.minimum.z);
+ newPoints[4] = QT3DSVec3(bounds.minimum.x, bounds.minimum.y, bounds.maximum.z);
+ newPoints[5] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.maximum.z);
+ newPoints[6] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.maximum.z);
+ newPoints[7] = bounds.maximum;
+ for (int i = 0; i < 8; ++i) {
+ // Transform the bounds into our local space.
+ points += localTransform.transform(newPoints[i]);
+ }
+ }
+}
+
+void SNode::GetActiveChildBoundsList(QVector<QT3DSVec3> &points, IBufferManager &inManager,
+ IPathManager &inPathManager,
+ QT3DSMat44 localTransform,
+ IQt3DSRenderNodeFilter *inChildFilter) const
+{
+ for (SNode *child = m_FirstChild; child != nullptr; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()
+ && (inChildFilter == nullptr || inChildFilter->IncludeNode(*child))) {
+ if (child->m_Flags.IsTransformDirty())
+ child->CalculateLocalTransform();
+ QT3DSMat44 nextTransform = localTransform * child->m_LocalTransform;
+ child->GetActiveBoundsList(points, inManager, inPathManager, nextTransform);
+ }
+ }
+}
+
QT3DSVec3 SNode::GetGlobalPos() const
{
return m_GlobalTransform.getPosition();
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderNode.h b/src/runtimerender/graphobjects/Qt3DSRenderNode.h
index 87a1500..7f5af1e 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderNode.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderNode.h
@@ -81,6 +81,7 @@ namespace render {
///mechanism. This can be usefulf or caching purposes.
IgnoreParentTransform = 1 << 13,
LayerEnableDepthPrePass = 1 << 14, ///< True when we render a depth pass before
+ ForceLoad = 1 << 15,
};
};
@@ -178,6 +179,14 @@ namespace render {
{
ClearOrSet(value, NodeFlagValues::LayerEnableDepthPrePass);
}
+ void SetForceLoad(bool value)
+ {
+ ClearOrSet(value, NodeFlagValues::ForceLoad);
+ }
+ bool IsForceLoad()
+ {
+ return this->operator&(NodeFlagValues::ForceLoad);
+ }
};
struct QT3DS_AUTOTEST_EXPORT SNode : public SGraphObject
@@ -201,6 +210,7 @@ namespace render {
QT3DSMat44 m_GlobalTransform;
QT3DSF32 m_GlobalOpacity;
QT3DSI32 m_SkeletonId;
+ bool m_ordered;
// node graph members.
SNode *m_Parent;
@@ -210,6 +220,8 @@ namespace render {
// Property maintained solely by the render system.
// Depth-first-search index assigned and maintained by render system.
QT3DSU32 m_DFSIndex;
+ // Index to the group of the node
+ QT3DSU32 m_GroupIndex;
SNode(GraphObjectTypes::Enum inType = GraphObjectTypes::Node);
SNode(const SNode &inCloningObject, NVAllocatorCallback &inAllocator);
@@ -268,9 +280,25 @@ namespace render {
// Get the bounds of us and our children in our local space.
NVBounds3 GetBounds(IBufferManager &inManager, IPathManager &inPathManager,
bool inIncludeChildren = true,
- IQt3DSRenderNodeFilter *inChildFilter = NULL) const;
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
NVBounds3 GetChildBounds(IBufferManager &inManager, IPathManager &inPathManager,
- IQt3DSRenderNodeFilter *inChildFilter = NULL) const;
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
+ NVBounds3 GetActiveBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ bool inIncludeChildren = true,
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
+ NVBounds3 GetActiveChildBounds(IBufferManager &inManager, IPathManager &inPathManager,
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
+ void GetActiveBoundsList(QVector<QT3DSVec3> &points,
+ IBufferManager &inManager,
+ IPathManager &inPathManager,
+ QT3DSMat44 localTransform = QT3DSMat44::createIdentity(),
+ bool inIncludeChildren = true,
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
+ void GetActiveChildBoundsList(QVector<QT3DSVec3> &points,
+ IBufferManager &inManager,
+ IPathManager &inPathManager,
+ QT3DSMat44 localTransform = QT3DSMat44::createIdentity(),
+ IQt3DSRenderNodeFilter *inChildFilter = nullptr) const;
// Assumes CalculateGlobalVariables has already been called.
QT3DSVec3 GetGlobalPos() const;
QT3DSVec3 GetGlobalPivot() const;
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderPresentation.h b/src/runtimerender/graphobjects/Qt3DSRenderPresentation.h
index 2403e3b..f777347 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderPresentation.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderPresentation.h
@@ -54,6 +54,7 @@ namespace render {
QT3DSVec2 m_PresentationDimensions;
RenderRotationValues::Enum m_PresentationRotation;
bool m_preferKTX;
+ bool m_flipCompressedTextures;
SScene *m_Scene;
CRegisteredString m_PresentationDirectory;
@@ -63,6 +64,7 @@ namespace render {
, m_PresentationDimensions(800, 400)
, m_PresentationRotation(RenderRotationValues::NoRotation)
, m_preferKTX(false)
+ , m_flipCompressedTextures(false)
, m_Scene(NULL)
{
}
@@ -72,6 +74,7 @@ namespace render {
, m_PresentationDimensions(w, h)
, m_PresentationRotation(RenderRotationValues::NoRotation)
, m_preferKTX(preferKTX)
+ , m_flipCompressedTextures(false)
, m_Scene(NULL)
, m_PresentationDirectory(presDir)
{
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp b/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp
index 2dadc26..3d14f9c 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderScene.cpp
@@ -42,6 +42,7 @@ SScene::SScene()
, m_ClearColor(0.0f)
, m_UseClearColor(true)
, m_Dirty(true)
+ , m_IsSubPresentationScene(false)
{
}
@@ -65,7 +66,7 @@ SLayer *SScene::GetLastChild()
return child;
}
-bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext,
+bool SScene::PrepareForRender(IQt3DSRenderContext &inContext,
const SRenderInstanceId id)
{
// We need to iterate through the layers in reverse order and ask them to render.
@@ -74,7 +75,7 @@ bool SScene::PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRende
if (m_FirstChild) {
wasDirty |=
- inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild, inViewportDimensions,
+ inContext.GetRenderer().PrepareLayerForRender(*m_FirstChild,
true, id);
}
return wasDirty;
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderScene.h b/src/runtimerender/graphobjects/Qt3DSRenderScene.h
index 8c4d3fe..a2f86b9 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderScene.h
+++ b/src/runtimerender/graphobjects/Qt3DSRenderScene.h
@@ -47,6 +47,7 @@ namespace render {
QT3DSVec4 m_ClearColor;
bool m_UseClearColor;
bool m_Dirty;
+ bool m_IsSubPresentationScene;
enum RenderClearCommand {
ClearIsOptional = 0,
@@ -69,7 +70,7 @@ namespace render {
inRemapper.Remap(m_FirstChild);
}
// returns true if any of the layers were dirty or if this object was dirty
- bool PrepareForRender(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext,
+ bool PrepareForRender(IQt3DSRenderContext &inContext,
const SRenderInstanceId id = nullptr);
void Render(const QT3DSVec2 &inViewportDimensions, IQt3DSRenderContext &inContext,
RenderClearCommand command = ClearIsOptional,
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderText.cpp b/src/runtimerender/graphobjects/Qt3DSRenderText.cpp
index 40a20c4..68e453b 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderText.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderText.cpp
@@ -46,7 +46,6 @@ STextRenderInfo::STextRenderInfo()
, m_Elide(TextElide::ElideNone)
, m_ScaleX(0)
, m_ScaleY(0)
- , m_EnableAcceleratedFont(false)
{
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
index 712214a..095badc 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.cpp
@@ -290,9 +290,31 @@ namespace render {
}
}
- context.SetCullingEnabled(true);
+ context.SetCullingEnabled(m_Material.m_CullMode != DefaultMaterialCullMode::None);
context.SetInputAssembler(m_Subset.m_InputAssembler);
- context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ if (m_Material.m_CullMode != DefaultMaterialCullMode::None) {
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rsdefaultstate =
+ context.CreateRasterizerState(0.0, 0.0, qt3ds::render::NVRenderFaces::Back);
+ qt3ds::render::NVRenderFaces::Enum face = qt3ds::render::NVRenderFaces::Back;
+ switch (m_Material.m_CullMode) {
+ case DefaultMaterialCullMode::Front:
+ face = qt3ds::render::NVRenderFaces::Front;
+ break;
+ case DefaultMaterialCullMode::FrontAndBack:
+ face = qt3ds::render::NVRenderFaces::FrontAndBack;
+ break;
+ default:
+ break;
+ }
+
+ NVScopedRefCounted<qt3ds::render::NVRenderRasterizerState> rasterState =
+ context.CreateRasterizerState(0.0, 0.0, face);
+ context.SetRasterizerState(rasterState);
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ context.SetRasterizerState(rsdefaultstate);
+ } else {
+ context.Draw(m_Subset.m_PrimitiveType, m_Subset.m_Count, m_Subset.m_Offset);
+ }
}
void SSubsetRenderable::RenderShadow(const QT3DSVec2 &inCameraVec,
@@ -600,5 +622,14 @@ namespace render {
theRenderContext, m_Generator.GetLayerGlobalRenderProperties(),
TShaderFeatureSet());
}
+
+ void SOrderedGroupRenderable::update()
+ {
+ QT3DSVec3 sum(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < m_renderables.size(); i++)
+ sum += m_renderables[i]->m_WorldCenterPoint;
+ sum *= 1.0f / m_renderables.size();
+ m_WorldCenterPoint = sum;
+ }
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
index abc8143..12533c4 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRenderableObjects.h
@@ -63,6 +63,7 @@ namespace render {
ShadowCaster = 1 << 10,
DistanceField = 1 << 11,
HasAlphaTest = 1 << 12,
+ OrderedGroup = 1 << 13,
};
};
@@ -167,6 +168,14 @@ namespace render {
{
return *this & RenderPreparationResultFlagValues::HasAlphaTest;
}
+ bool isOrderedGroup() const
+ {
+ return *this & RenderPreparationResultFlagValues::OrderedGroup;
+ }
+ void setOrderedGroup(bool ordered)
+ {
+ ClearOrSet(ordered, RenderPreparationResultFlagValues::OrderedGroup);
+ }
};
struct SNodeLightEntry
@@ -480,6 +489,20 @@ namespace render {
void RenderShadowMapPass(const QT3DSVec2 &inCameraVec, const SLight *inLight,
const SCamera &inCamera, SShadowMapEntry *inShadowMapEntry);
};
+
+ struct SOrderedGroupRenderable : public SRenderableObject
+ {
+ SOrderedGroupRenderable(SRenderableObjectFlags inFlags, const QT3DSVec3 &inWorldCenterPt,
+ const QT3DSMat44 &inGlobalTransform, const NVBounds3 &inBounds,
+ NVAllocatorCallback &allocator)
+ : SRenderableObject(inFlags, inWorldCenterPt, inGlobalTransform, inBounds)
+ , m_renderables(allocator, "SOrderedGroupRenderable::m_renderables")
+ {
+ m_RenderableFlags.setOrderedGroup(true);
+ }
+ void update();
+ nvvector<SRenderableObject *> m_renderables;
+ };
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
index a0ea8b1..b39cc91 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.cpp
@@ -57,6 +57,7 @@
#include "Qt3DSRenderPath.h"
#include "Qt3DSRenderShaderCodeGeneratorV2.h"
#include "Qt3DSRenderDefaultMaterialShaderGenerator.h"
+#include "backends/gl/Qt3DSOpenGLUtil.h"
#include <stdlib.h>
#ifdef _WIN32
@@ -128,6 +129,7 @@ namespace render {
, m_PickRenderPlugins(true)
, m_LayerCachingEnabled(true)
, m_LayerGPuProfilingEnabled(false)
+ , m_SignalProxy(ctx.GetSignalProxy())
{
}
Qt3DSRendererImpl::~Qt3DSRendererImpl()
@@ -232,11 +234,9 @@ namespace render {
}
bool Qt3DSRendererImpl::PrepareLayerForRender(SLayer &inLayer,
- const QT3DSVec2 &inViewportDimensions,
bool inRenderSiblings,
const SRenderInstanceId id)
{
- (void)inViewportDimensions;
nvvector<SLayer *> renderableLayers(m_qt3dsContext.GetPerFrameAllocator(), "LayerVector");
// Found by fair roll of the dice.
renderableLayers.reserve(4);
@@ -253,7 +253,7 @@ namespace render {
SLayerRenderData *theRenderData = GetOrCreateLayerRenderDataForNode(*theLayer, id);
if (theRenderData) {
- theRenderData->PrepareForRender();
+ bool needsRender = theRenderData->PrepareForRender();
if (id) {
if (m_initialPrepareData.contains(theLayer)) {
// Copy dirty state from the initial since the graph is
@@ -268,7 +268,8 @@ namespace render {
m_initialPrepareData.insert(theLayer, theRenderData);
}
}
- retval = retval || theRenderData->m_LayerPrepResult->m_Flags.WasDirty();
+ retval = retval || needsRender
+ || theRenderData->m_LayerPrepResult->m_Flags.WasDirty() ;
} else {
QT3DS_ASSERT(false);
}
@@ -367,7 +368,7 @@ namespace render {
SLayerRenderData *theRenderData = QT3DS_NEW(m_Context->GetAllocator(), SLayerRenderData)(
const_cast<SLayer &>(*theLayer), *this);
m_InstanceRenderMap.insert(make_pair(combineLayerAndId(theLayer, id), theRenderData));
-
+ theRenderData->m_SignalProxy = (QRuntimeViewSignalProxy *)m_SignalProxy;
// create a profiler if enabled
if (IsLayerGpuProfilingEnabled() && theRenderData)
theRenderData->CreateGpuProfiler();
@@ -968,20 +969,53 @@ namespace render {
return mouseVec;
}
- uint Qt3DSRendererImpl::getLayerTextureId(SLayer &layer)
+ uint Qt3DSRendererImpl::getLayerTextureId(SLayer &layer, const SRenderInstanceId id)
{
- SLayerRenderData *data = GetOrCreateLayerRenderDataForNode(layer);
- if (data->m_LayerCachedTexture) {
+ SLayerRenderData *data = GetOrCreateLayerRenderDataForNode(layer, id);
+ if (data->m_LayerCachedTexture[data->getCameraIndex()]) {
return static_cast<uint>(reinterpret_cast<size_t>(
- data->m_LayerCachedTexture->GetTextureObjectHandle()));
+ data->m_LayerCachedTexture[data->getCameraIndex()]->GetTextureObjectHandle()));
}
- if (data->m_LayerTexture) {
+ if (data->m_LayerTexture[data->getCameraIndex()]) {
return static_cast<uint>(reinterpret_cast<size_t>(
- data->m_LayerTexture->GetTextureObjectHandle()));
+ data->m_LayerTexture[data->getCameraIndex()]->GetTextureObjectHandle()));
}
return 0;
}
+ GLenum Qt3DSRendererImpl::getTextureGlFormat(NVRenderTextureFormats::Enum internalFormat)
+ {
+ auto ctxType = m_Context->GetRenderContextType();
+ GLConversion conversion;
+ GLenum glInternalFormat, glformat, gltype;
+
+ if (NVRenderTextureFormats::isUncompressedTextureFormat(internalFormat)) {
+ conversion.fromUncompressedTextureFormatToGL(ctxType, internalFormat,
+ glformat, gltype, glInternalFormat);
+ return glInternalFormat;
+ } else if (NVRenderTextureFormats::isCompressedTextureFormat(internalFormat)) {
+ return conversion.fromCompressedTextureFormatToGL(internalFormat);
+ } else if (NVRenderTextureFormats::isDepthTextureFormat(internalFormat)) {
+ conversion.fromDepthTextureFormatToGL(ctxType, internalFormat, glformat,
+ gltype, glInternalFormat);
+ return glInternalFormat;
+ } else {
+ return GL_INVALID_ENUM;
+ }
+ }
+
+ STextureDetails Qt3DSRendererImpl::getLayerTextureDetails(SLayer &inLayer, const SRenderInstanceId id)
+ {
+ SLayerRenderData *theData = GetOrCreateLayerRenderDataForNode(inLayer, id);
+
+ if (theData->m_LayerCachedTexture[theData->getCameraIndex()])
+ return theData->m_LayerCachedTexture[theData->getCameraIndex()]->GetTextureDetails();
+ if (theData->m_LayerTexture[theData->getCameraIndex()])
+ return theData->m_LayerTexture[theData->getCameraIndex()]->GetTextureDetails();
+
+ return {};
+ }
+
Option<SLayerPickSetup> Qt3DSRendererImpl::GetLayerPickSetup(SLayer &inLayer,
const QT3DSVec2 &inMouseCoords,
const QSize &inPickDims)
@@ -1405,61 +1439,72 @@ namespace render {
}
void Qt3DSRendererImpl::GetLayerHitObjectList(SLayerRenderData &inLayerRenderData,
- const QT3DSVec2 &inViewportDimensions,
- const QT3DSVec2 &inPresCoords, bool inPickEverything,
- TPickResultArray &outIntersectionResult,
- NVAllocatorCallback &inTempAllocator)
+ const QT3DSVec2 &inViewportDimensions,
+ const QT3DSVec2 &inPresCoords,
+ bool inPickEverything,
+ TPickResultArray &outIntersectionResult,
+ NVAllocatorCallback &inTempAllocator)
{
// This function assumes the layer was rendered to the scene itself. There is another
- // function
- // for completely offscreen layers that don't get rendered to the scene.
+ // function for completely offscreen layers that don't get rendered to the scene.
bool wasRenderToTarget(inLayerRenderData.m_Layer.m_Flags.IsLayerRenderToTarget());
- if (wasRenderToTarget && inLayerRenderData.m_Camera != nullptr) {
- Option<SRay> theHitRay;
- if (inLayerRenderData.m_LayerPrepResult.hasValue()) {
- theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
- inPresCoords, inViewportDimensions, false, m_Context->isSceneCameraView());
- }
- if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr == nullptr) {
- if (theHitRay.hasValue()) {
- // Scale the mouse coords to change them into the camera's numerical space.
- SRay thePickRay = *theHitRay;
- for (QT3DSU32 idx = inLayerRenderData.m_OpaqueObjects.size(), end = 0; idx > end;
- --idx) {
- SRenderableObject *theRenderableObject =
- inLayerRenderData.m_OpaqueObjects[idx - 1];
- if (inPickEverything
- || theRenderableObject->m_RenderableFlags.GetPickable())
- IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
- outIntersectionResult,
- inTempAllocator);
- }
- for (QT3DSU32 idx = inLayerRenderData.m_TransparentObjects.size(), end = 0;
- idx > end; --idx) {
- SRenderableObject *theRenderableObject =
- inLayerRenderData.m_TransparentObjects[idx - 1];
- if (inPickEverything
- || theRenderableObject->m_RenderableFlags.GetPickable())
- IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
- outIntersectionResult,
- inTempAllocator);
- }
+ if (!wasRenderToTarget || !inLayerRenderData.m_Camera)
+ return;
+
+ Option<SRay> theHitRay;
+ if (inLayerRenderData.m_LayerPrepResult.hasValue()) {
+ theHitRay = inLayerRenderData.m_LayerPrepResult->GetPickRay(
+ inPresCoords, inViewportDimensions, false, m_Context->isSceneCameraView());
+ }
+ if (inLayerRenderData.m_LastFrameOffscreenRenderer.mPtr) {
+ IGraphObjectPickQuery *theQuery =
+ inLayerRenderData.m_LastFrameOffscreenRenderer->GetGraphObjectPickQuery(this);
+ if (theQuery) {
+ Qt3DSRenderPickResult theResult =
+ theQuery->Pick(inPresCoords, inViewportDimensions, inPickEverything);
+ if (theResult.m_HitObject) {
+ theResult.m_OffscreenRenderer =
+ inLayerRenderData.m_LastFrameOffscreenRenderer;
+ outIntersectionResult.push_back(theResult);
}
} else {
- IGraphObjectPickQuery *theQuery =
- inLayerRenderData.m_LastFrameOffscreenRenderer->GetGraphObjectPickQuery(this);
- if (theQuery) {
- Qt3DSRenderPickResult theResult =
- theQuery->Pick(inPresCoords, inViewportDimensions, inPickEverything);
- if (theResult.m_HitObject) {
- theResult.m_OffscreenRenderer =
- inLayerRenderData.m_LastFrameOffscreenRenderer;
- outIntersectionResult.push_back(theResult);
- }
- } else
- inLayerRenderData.m_LastFrameOffscreenRenderer->Pick(inPresCoords,
- inViewportDimensions,
- this);
+ inLayerRenderData.m_LastFrameOffscreenRenderer->Pick(inPresCoords,
+ inViewportDimensions,
+ this);
+ }
+ return;
+ }
+ if (!theHitRay.hasValue())
+ return;
+ // Scale the mouse coords to change them into the camera's coordinate space.
+ SRay thePickRay = *theHitRay;
+ for (QT3DSU32 idx = inLayerRenderData.m_OpaqueObjects.size(), end = 0; idx > end; --idx) {
+ SRenderableObject *theRenderableObject = inLayerRenderData.m_OpaqueObjects[idx - 1];
+ if (inPickEverything || theRenderableObject->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *theRenderableObject,
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ }
+ for (QT3DSU32 idx = inLayerRenderData.m_GroupObjects.size(), end = 0; idx > end; --idx) {
+ SRenderableObject *object = inLayerRenderData.m_GroupObjects[idx - 1];
+ SOrderedGroupRenderable &group(static_cast<SOrderedGroupRenderable &>(*object));
+ Q_ASSERT(object->m_RenderableFlags.isOrderedGroup());
+ for (int i = 0; i < group.m_renderables.size(); ++i) {
+ if (inPickEverything || group.m_renderables[i]->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *group.m_renderables[i],
+ outIntersectionResult,
+ inTempAllocator);
+ }
+ }
+ }
+ for (QT3DSU32 idx = inLayerRenderData.m_TransparentObjects.size(), end = 0;
+ idx > end; --idx) {
+ SRenderableObject *renderableObject = inLayerRenderData.m_TransparentObjects[idx - 1];
+ if (inPickEverything || renderableObject->m_RenderableFlags.GetPickable()) {
+ IntersectRayWithSubsetRenderable(thePickRay, *renderableObject,
+ outIntersectionResult,
+ inTempAllocator);
}
}
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
index 792d71e..2230733 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImpl.h
@@ -296,6 +296,7 @@ namespace render {
bool m_PickRenderPlugins;
bool m_LayerCachingEnabled;
bool m_LayerGPuProfilingEnabled;
+ void *m_SignalProxy;
SShaderDefaultMaterialKeyProperties m_DefaultMaterialShaderKeyProperties;
QHash<SLayer *, SLayerRenderData *> m_initialPrepareData;
@@ -305,6 +306,7 @@ namespace render {
float m_alphaOp = 1.0f;
float m_alphaRef = 1.0f;
+
public:
Qt3DSRendererImpl(IQt3DSRenderContext &ctx);
virtual ~Qt3DSRendererImpl();
@@ -342,8 +344,8 @@ namespace render {
// Calls prepare layer for render
// and then do render layer.
- bool PrepareLayerForRender(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
- bool inRenderSiblings, const SRenderInstanceId id) override;
+ bool PrepareLayerForRender(SLayer &inLayer, bool inRenderSiblings,
+ const SRenderInstanceId id) override;
void RenderLayer(SLayer &inLayer, const QT3DSVec2 &inViewportDimensions,
bool clear, QT3DSVec4 clearColor, bool inRenderSiblings,
const SRenderInstanceId id) override;
@@ -386,7 +388,11 @@ namespace render {
const QT3DSVec3 &inMouseVec) const override;
QT3DSVec3 ProjectPosition(SNode &inNode, const QT3DSVec3 &inPosition) const override;
- uint getLayerTextureId(SLayer &layer) override;
+ uint getLayerTextureId(SLayer &layer, const SRenderInstanceId id) override;
+
+ STextureDetails getLayerTextureDetails(SLayer &inLayer, const SRenderInstanceId id) override;
+
+ GLenum getTextureGlFormat(NVRenderTextureFormats::Enum internalFormat) override;
Option<SLayerPickSetup> GetLayerPickSetup(SLayer &inLayer,
const QT3DSVec2 &inMouseCoords,
@@ -566,7 +572,6 @@ namespace render {
Option<QT3DSVec2> GetLayerMouseCoords(SLayer &inLayer, const QT3DSVec2 &inMouseCoords,
const QT3DSVec2 &inViewportDimensions,
bool forceImageIntersect = false) const override;
-
protected:
Option<QT3DSVec2> GetLayerMouseCoords(SLayerRenderData &inLayer, const QT3DSVec2 &inMouseCoords,
const QT3DSVec2 &inViewportDimensions,
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
index 95cbc9e..7348fb2 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.cpp
@@ -77,7 +77,8 @@ namespace render {
SLayerRenderData::SLayerRenderData(SLayer &inLayer, Qt3DSRendererImpl &inRenderer)
: SLayerRenderPreparationData(inLayer, inRenderer)
- , m_LayerTexture(inRenderer.GetQt3DSContext().GetResourceManager())
+ , m_LayerTexture{inRenderer.GetQt3DSContext().GetResourceManager(),
+ inRenderer.GetQt3DSContext().GetResourceManager()}
, m_TemporalAATexture{inRenderer.GetQt3DSContext().GetResourceManager(),
inRenderer.GetQt3DSContext().GetResourceManager()}
, m_LayerDepthTexture(inRenderer.GetQt3DSContext().GetResourceManager())
@@ -87,7 +88,7 @@ namespace render {
, m_LayerMultisampleTexture(inRenderer.GetQt3DSContext().GetResourceManager())
, m_LayerMultisamplePrepassDepthTexture(inRenderer.GetQt3DSContext().GetResourceManager())
, m_LayerMultisampleWidgetTexture(inRenderer.GetQt3DSContext().GetResourceManager())
- , m_LayerCachedTexture(NULL)
+ , m_LayerCachedTexture{NULL, NULL}
, m_AdvancedBlendDrawTexture(NULL)
, m_AdvancedBlendBlendTexture(NULL)
, m_AdvancedModeDrawFB(NULL)
@@ -105,8 +106,10 @@ namespace render {
SLayerRenderData::~SLayerRenderData()
{
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
- if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture)
- theResourceManager.Release(*m_LayerCachedTexture);
+ if (m_LayerCachedTexture[0] && m_LayerCachedTexture[0] != m_LayerTexture[0])
+ theResourceManager.Release(*m_LayerCachedTexture[0]);
+ if (m_LayerCachedTexture[1] && m_LayerCachedTexture[1] != m_LayerTexture[1])
+ theResourceManager.Release(*m_LayerCachedTexture[1]);
if (m_AdvancedModeDrawFB) {
m_AdvancedModeDrawFB->release();
m_AdvancedModeDrawFB = NULL;
@@ -120,9 +123,9 @@ namespace render {
if (m_AdvancedBlendDrawTexture)
m_AdvancedBlendDrawTexture = NULL;
}
- void SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions)
+ bool SLayerRenderData::PrepareForRender(const QSize &inViewportDimensions)
{
- SLayerRenderPreparationData::PrepareForRender(inViewportDimensions);
+ bool needsRender = SLayerRenderPreparationData::PrepareForRender(inViewportDimensions);
SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
@@ -133,13 +136,13 @@ namespace render {
}
// Get rid of the layer texture if we aren't rendering to texture this frame.
- if (m_LayerTexture && !thePrepResult.m_Flags.ShouldRenderToTexture()) {
- if (m_LayerCachedTexture && m_LayerCachedTexture != m_LayerTexture) {
- theResourceManager.Release(*m_LayerCachedTexture);
- m_LayerCachedTexture = NULL;
+ if (m_LayerTexture[getCameraIndex()] && !thePrepResult.m_Flags.ShouldRenderToTexture()) {
+ if (m_LayerCachedTexture[getCameraIndex()] && m_LayerCachedTexture[getCameraIndex()] != m_LayerTexture[getCameraIndex()]) {
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = NULL;
}
- m_LayerTexture.ReleaseTexture();
+ m_LayerTexture[getCameraIndex()].ReleaseTexture();
m_LayerDepthTexture.ReleaseTexture();
m_LayerWidgetTexture.ReleaseTexture();
m_LayerSsaoTexture.ReleaseTexture();
@@ -162,7 +165,7 @@ namespace render {
// Clean up the texture cache if layer dimensions changed
if (inViewportDimensions.width() != m_previousDimensions.width()
|| inViewportDimensions.height() != m_previousDimensions.height()) {
- m_LayerTexture.ReleaseTexture();
+ m_LayerTexture[getCameraIndex()].ReleaseTexture();
m_LayerDepthTexture.ReleaseTexture();
m_LayerSsaoTexture.ReleaseTexture();
m_LayerWidgetTexture.ReleaseTexture();
@@ -182,6 +185,13 @@ namespace render {
m_Renderer.GetQt3DSContext().GetEffectSystem().GetResourceManager()
.DestroyFreeSizedResources();
}
+ bool isProgressiveAABlendPass =
+ m_ProgressiveAAPassIndex && m_ProgressiveAAPassIndex < thePrepResult.m_MaxAAPassIndex;
+ // Save left eye flags for later
+ if (getCameraIndex() == 0)
+ m_LeftFlags = SLayerRenderPreparationResultFlags(thePrepResult.m_Flags);
+
+ return needsRender || isProgressiveAABlendPass;
}
NVRenderTextureFormats::Enum SLayerRenderData::GetDepthBufferFormat()
@@ -309,6 +319,36 @@ namespace render {
}
namespace {
+ NVBounds3 calculateShadowCameraBoundingBox(const QT3DSVec3 *points,
+ const QT3DSVec3 &forward,
+ const QT3DSVec3 &up, const QT3DSVec3 &right)
+ {
+ float minDistanceZ = std::numeric_limits<float>::max();
+ float maxDistanceZ = -std::numeric_limits<float>::max();
+ float minDistanceY = std::numeric_limits<float>::max();
+ float maxDistanceY = -std::numeric_limits<float>::max();
+ float minDistanceX = std::numeric_limits<float>::max();
+ float maxDistanceX = -std::numeric_limits<float>::max();
+ for (int i = 0; i < 8; ++i) {
+ float distanceZ = points[i].dot(forward);
+ if (distanceZ < minDistanceZ)
+ minDistanceZ = distanceZ;
+ if (distanceZ > maxDistanceZ)
+ maxDistanceZ = distanceZ;
+ float distanceY = points[i].dot(up);
+ if (distanceY < minDistanceY)
+ minDistanceY = distanceY;
+ if (distanceY > maxDistanceY)
+ maxDistanceY = distanceY;
+ float distanceX = points[i].dot(right);
+ if (distanceX < minDistanceX)
+ minDistanceX = distanceX;
+ if (distanceX > maxDistanceX)
+ maxDistanceX = distanceX;
+ }
+ return NVBounds3(QT3DSVec3(minDistanceX, minDistanceY, minDistanceZ),
+ QT3DSVec3(maxDistanceX, maxDistanceY, maxDistanceZ));
+ }
void computeFrustumBounds(const SCamera &inCamera, const NVRenderRectF &inViewPort,
QT3DSVec3 &ctrBound, QT3DSVec3 camVerts[8])
@@ -350,7 +390,8 @@ namespace render {
void SetupCameraForShadowMap(const QT3DSVec2 &inCameraVec, NVRenderContext & /*inContext*/,
const NVRenderRectF &inViewport, const SCamera &inCamera,
- const SLight *inLight, SCamera &theCamera)
+ const SLight *inLight, SCamera &theCamera,
+ QT3DSVec3 *scenePoints = nullptr)
{
// setup light matrix
QT3DSU32 mapRes = 1 << inLight->m_ShadowMapRes;
@@ -368,8 +409,15 @@ namespace render {
theCamera.m_FOV = inLight->m_ShadowMapFov * QT3DS_DEGREES_TO_RADIANS;
if (inLight->m_LightType == RenderLightTypes::Directional) {
- QT3DSVec3 frustBounds[8], boundCtr;
- computeFrustumBounds(inCamera, inViewport, boundCtr, frustBounds);
+ QT3DSVec3 frustumPoints[8], boundCtr, sceneCtr;
+ computeFrustumBounds(inCamera, inViewport, boundCtr, frustumPoints);
+
+ if (scenePoints) {
+ sceneCtr = QT3DSVec3(0, 0, 0);
+ for (int i = 0; i < 8; ++i)
+ sceneCtr += scenePoints[i];
+ sceneCtr *= 0.125f;
+ }
QT3DSVec3 forward = inLightDir;
forward.normalize();
@@ -379,37 +427,26 @@ namespace render {
up.normalize();
// Calculate bounding box of the scene camera frustum
- float minDistanceZ = std::numeric_limits<float>::max();
- float maxDistanceZ = -std::numeric_limits<float>::max();
- float minDistanceY = std::numeric_limits<float>::max();
- float maxDistanceY = -std::numeric_limits<float>::max();
- float minDistanceX = std::numeric_limits<float>::max();
- float maxDistanceX = -std::numeric_limits<float>::max();
- for (int i = 0; i < 8; ++i) {
- float distanceZ = frustBounds[i].dot(forward);
- if (distanceZ < minDistanceZ)
- minDistanceZ = distanceZ;
- if (distanceZ > maxDistanceZ)
- maxDistanceZ = distanceZ;
- float distanceY = frustBounds[i].dot(up);
- if (distanceY < minDistanceY)
- minDistanceY = distanceY;
- if (distanceY > maxDistanceY)
- maxDistanceY = distanceY;
- float distanceX = frustBounds[i].dot(right);
- if (distanceX < minDistanceX)
- minDistanceX = distanceX;
- if (distanceX > maxDistanceX)
- maxDistanceX = distanceX;
+ NVBounds3 bounds = calculateShadowCameraBoundingBox(frustumPoints, forward, up,
+ right);
+ inLightPos = boundCtr;
+ if (scenePoints) {
+ NVBounds3 sceneBounds = calculateShadowCameraBoundingBox(scenePoints, forward,
+ up, right);
+ if (sceneBounds.getExtents().x * sceneBounds.getExtents().y
+ * sceneBounds.getExtents().z < bounds.getExtents().x
+ * bounds.getExtents().y * bounds.getExtents().z) {
+ bounds = sceneBounds;
+ inLightPos = sceneCtr;
+ }
}
// Apply bounding box parameters to shadow map camera projection matrix
// so that the whole scene is fit inside the shadow map
- inLightPos = boundCtr;
- theViewport.m_Height = abs(maxDistanceY - minDistanceY);
- theViewport.m_Width = abs(maxDistanceX - minDistanceX);
- theCamera.m_ClipNear = -abs(maxDistanceZ - minDistanceZ);
- theCamera.m_ClipFar = abs(maxDistanceZ - minDistanceZ);
+ theViewport.m_Height = bounds.getExtents().y * 2;
+ theViewport.m_Width = bounds.getExtents().x * 2;
+ theCamera.m_ClipNear = -bounds.getExtents().z * 2;
+ theCamera.m_ClipFar = bounds.getExtents().z * 2;
}
theCamera.m_Flags.SetLeftHanded(false);
@@ -668,14 +705,15 @@ namespace render {
void SLayerRenderData::RenderShadowMapPass(CResourceFrameBuffer *theFB)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::RenderShadowMapPass")
+ "LayerRenderData: RenderShadowMapPass")
if (m_Camera == NULL || !GetShadowMapManager())
return;
// Check if we have anything to render
- if ((m_OpaqueObjects.size() == 0 && GetTransparentRenderableObjects().size() == 0)
- || m_Lights.size() == 0) {
+ if ((m_OpaqueObjects.empty() && GetTransparentRenderableObjects().size() == 0
+ && m_GroupObjects.empty())
+ || m_Lights.empty()) {
return;
}
@@ -706,6 +744,18 @@ namespace render {
| qt3ds::render::NVRenderClearValues::Stencil
| qt3ds::render::NVRenderClearValues::Color);
+ auto bounds = m_Camera->m_Parent->GetBounds(m_Renderer.GetQt3DSContext().GetBufferManager(),
+ m_Renderer.GetQt3DSContext().GetPathManager());
+ QT3DSVec3 scenePoints[8];
+ scenePoints[0] = bounds.minimum;
+ scenePoints[1] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.minimum.z);
+ scenePoints[2] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.minimum.z);
+ scenePoints[3] = QT3DSVec3(bounds.maximum.x, bounds.maximum.y, bounds.minimum.z);
+ scenePoints[4] = QT3DSVec3(bounds.minimum.x, bounds.minimum.y, bounds.maximum.z);
+ scenePoints[5] = QT3DSVec3(bounds.maximum.x, bounds.minimum.y, bounds.maximum.z);
+ scenePoints[6] = QT3DSVec3(bounds.minimum.x, bounds.maximum.y, bounds.maximum.z);
+ scenePoints[7] = bounds.maximum;
+
for (QT3DSU32 i = 0; i < m_Lights.size(); i++) {
// don't render shadows when not casting
if (m_Lights[i]->m_CastShadow == false)
@@ -717,7 +767,7 @@ namespace render {
QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
SetupCameraForShadowMap(theCameraProps, m_Renderer.GetContext(),
__viewport.m_InitialValue, *m_Camera,
- m_Lights[i], theCamera);
+ m_Lights[i], theCamera, scenePoints);
// we need this matrix for the final rendering
theCamera.CalculateViewProjectionMatrix(pEntry->m_LightVP);
pEntry->m_LightView = theCamera.m_GlobalTransform.getInverse();
@@ -826,13 +876,13 @@ namespace render {
void SLayerRenderData::RenderDepthPass(bool inEnableTransparentDepthWrite)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::RenderDepthPass")
+ "LayerRenderData: RenderDepthPass")
if (m_Camera == NULL)
return;
// Avoid running this method if possible.
- if ((inEnableTransparentDepthWrite == false
- && ((m_OpaqueObjects.size() == 0 && m_TransparentObjects.size() == 0)
+ if ((inEnableTransparentDepthWrite
+ && ((m_GroupObjects.empty() && m_OpaqueObjects.empty() && m_TransparentObjects.empty())
|| m_Layer.m_Flags.IsLayerEnableDepthPrepass() == false))
|| m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
return;
@@ -895,23 +945,98 @@ namespace render {
}
}
- void SLayerRenderData::renderTransparentObjectsPass(
- TRenderRenderableFunction inRenderFn, bool inEnableBlending,
- bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
- const SCamera &inCamera, CResourceFrameBuffer *theFB)
- {
- NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
- NVRenderContext &theRenderContext(m_Renderer.GetContext());
- QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
- if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
- theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+void SLayerRenderData::renderOrderedGroup(
+ SRenderableObject &theObject, TRenderRenderableFunction inRenderFn, bool inEnableBlending,
+ bool inEnableDepthWrite, bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ SOrderedGroupRenderable &group(static_cast<SOrderedGroupRenderable &>(theObject));
+ const bool opaqueDepthTest = m_Layer.m_Flags.IsLayerEnableDepthTest();
+ const bool opaqueDepthWrite = opaqueDepthTest && inEnableDepthWrite;
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ for (int i = 0; i < group.m_renderables.size(); ++i) {
+ SRenderableObject &object(*group.m_renderables[i]);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ SScopedLightsListScope lightsScope(m_Lights, m_LightDirections,
+ m_SourceLightDirections,
+ object.m_ScopedLights);
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Renders transparent objects to a separate FBO and blends them in shader
+ // with the opaque items and background.
+ DefaultMaterialBlendMode::Enum blendMode
+ = DefaultMaterialBlendMode::Enum::Normal;
+ if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
+ blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR() && m_LayerPrepassDepthTexture;
+ if (useBlendFallback)
+ SetupDrawFB(true);
+#endif
+ if (object.m_RenderableFlags.hasAlphaTest()) {
+ theRenderContext.SetBlendingEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ m_Renderer.setAlphaTest(false, 1.0, 1.0);
+ } else {
+ const bool transparency
+ = object.m_RenderableFlags.HasTransparency() && inEnableBlending;
+ theRenderContext.SetBlendingEnabled(transparency);
+ theRenderContext.SetDepthWriteEnabled((!transparency && opaqueDepthWrite)
+ || inEnableTransparentDepthWrite);
+ inRenderFn(*this, object, theCameraProps, GetShaderFeatureSet(), indexLight,
+ inCamera);
+ }
+#ifdef ADVANCED_BLEND_SW_FALLBACK
+ // SW fallback for advanced blend modes.
+ // Continue blending after transparent objects have been rendered to a FBO
+ if (useBlendFallback) {
+ BlendAdvancedToFB(blendMode, true, theFB);
+ // restore blending status
+ theRenderContext.SetBlendingEnabled(inEnableBlending);
+ // restore depth test status
+ theRenderContext.SetDepthTestEnabled(
+ m_Layer.m_Flags.IsLayerEnableDepthTest());
theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+ }
+#endif
+ }
+}
- // Assume all objects have transparency if the layer's depth test enabled flag is true.
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() == true) {
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
- if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+void SLayerRenderData::renderTransparentObjectsPass(
+ TRenderRenderableFunction inRenderFn, bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ if (inEnableBlending || m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
+ theRenderContext.SetBlendingEnabled(true && inEnableBlending);
+ theRenderContext.SetDepthWriteEnabled(inEnableTransparentDepthWrite);
+
+ // Assume all objects have transparency if the layer's depth test enabled flag is true.
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest()) {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ if (theObject.m_RenderableFlags.isOrderedGroup()) {
+ renderOrderedGroup(theObject, inRenderFn, inEnableBlending,
+ inEnableDepthWrite, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
+ } else {
#ifdef ADVANCED_BLEND_SW_FALLBACK
// SW fallback for advanced blend modes.
// Renders transparent objects to a separate FBO and blends them in shader
@@ -920,12 +1045,13 @@ namespace render {
= DefaultMaterialBlendMode::Enum::Normal;
if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
- bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
- blendMode == DefaultMaterialBlendMode::ColorBurn ||
- blendMode == DefaultMaterialBlendMode::ColorDodge) &&
- !theRenderContext.IsAdvancedBlendHwSupported() &&
- !theRenderContext.IsAdvancedBlendHwSupportedKHR() &&
- m_LayerPrepassDepthTexture;
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR()
+ && m_LayerPrepassDepthTexture;
if (useBlendFallback)
SetupDrawFB(true);
#endif
@@ -934,6 +1060,11 @@ namespace render {
theObject.m_ScopedLights);
SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
indexLight, inCamera);
#ifdef ADVANCED_BLEND_SW_FALLBACK
@@ -952,22 +1083,29 @@ namespace render {
}
}
}
- // If the layer doesn't have depth enabled then we have to render via an alternate route
- // where the transparent objects vector could have both opaque and transparent objects.
- else {
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
- if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ }
+ // If the layer doesn't have depth enabled then we have to render via an alternate route
+ // where the transparent objects vector could have both opaque and transparent objects.
+ else {
+ for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
+ SRenderableObject &theObject(*theTransparentObjects[idx]);
+ if (!(theObject.m_RenderableFlags.IsCompletelyTransparent())) {
+ if (theObject.m_RenderableFlags.isOrderedGroup()) {
+ renderOrderedGroup(theObject, inRenderFn, inEnableBlending,
+ inEnableDepthWrite, inEnableTransparentDepthWrite,
+ indexLight, inCamera, theFB);
+ } else {
#ifdef ADVANCED_BLEND_SW_FALLBACK
DefaultMaterialBlendMode::Enum blendMode
= DefaultMaterialBlendMode::Enum::Normal;
if (theObject.m_RenderableFlags.IsDefaultMaterialMeshSubset())
blendMode = static_cast<SSubsetRenderable &>(theObject).getBlendingMode();
- bool useBlendFallback = (blendMode == DefaultMaterialBlendMode::Overlay ||
- blendMode == DefaultMaterialBlendMode::ColorBurn ||
- blendMode == DefaultMaterialBlendMode::ColorDodge) &&
- !theRenderContext.IsAdvancedBlendHwSupported() &&
- !theRenderContext.IsAdvancedBlendHwSupportedKHR();
+ bool useBlendFallback
+ = (blendMode == DefaultMaterialBlendMode::Overlay
+ || blendMode == DefaultMaterialBlendMode::ColorBurn
+ || blendMode == DefaultMaterialBlendMode::ColorDodge)
+ && !theRenderContext.IsAdvancedBlendHwSupported()
+ && !theRenderContext.IsAdvancedBlendHwSupportedKHR();
if (theObject.m_RenderableFlags.HasTransparency()) {
theRenderContext.SetBlendingEnabled(true && inEnableBlending);
@@ -982,6 +1120,12 @@ namespace render {
m_SourceLightDirections,
theObject.m_ScopedLights);
SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(),
indexLight, inCamera);
#ifdef ADVANCED_BLEND_SW_FALLBACK
@@ -996,65 +1140,63 @@ namespace render {
}
}
}
- };
-
- void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
- bool inEnableBlending, bool inEnableDepthWrite,
- bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
- const SCamera &inCamera, CResourceFrameBuffer *theFB)
+ }
+};
+
+void SLayerRenderData::RunRenderPass(TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB)
+{
+ NVRenderContext &theRenderContext(m_Renderer.GetContext());
+ theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
+ theRenderContext.SetBlendingEnabled(false);
+ QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
{
- NVRenderContext &theRenderContext(m_Renderer.GetContext());
- theRenderContext.SetDepthFunction(qt3ds::render::NVRenderBoolOp::LessThanOrEqual);
- theRenderContext.SetBlendingEnabled(false);
- QT3DSVec2 theCameraProps = QT3DSVec2(m_Camera->m_ClipNear, m_Camera->m_ClipFar);
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render opaque")
NVDataRef<SRenderableObject *> theOpaqueObjects = GetOpaqueRenderableObjects();
- if (m_Layer.m_Flags.IsLayerEnableDepthTest()) {
- theRenderContext.SetDepthTestEnabled(true);
- theRenderContext.SetDepthWriteEnabled(inEnableDepthWrite);
- } else {
- theRenderContext.SetDepthWriteEnabled(false);
- theRenderContext.SetDepthTestEnabled(false);
- }
+ const bool opaqueDepthTest = m_Layer.m_Flags.IsLayerEnableDepthTest();
+ const bool opaqueDepthWrite = opaqueDepthTest && inEnableDepthWrite;
+
+ theRenderContext.SetDepthTestEnabled(opaqueDepthTest);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
for (QT3DSU32 idx = 0, end = theOpaqueObjects.size(); idx < end; ++idx) {
SRenderableObject &theObject(*theOpaqueObjects[idx]);
- SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
- theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
- inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
- inCamera);
- }
- NVDataRef<SRenderableObject *> theTransparentObjects = GetTransparentRenderableObjects();
- // Also draw opaque parts of transparent objects
- m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
- for (QT3DSU32 idx = 0, end = theTransparentObjects.size(); idx < end; ++idx) {
- SRenderableObject &theObject(*theTransparentObjects[idx]);
+ QT3DS_ASSERT(!theObject.m_RenderableFlags.isOrderedGroup());
+
+ theRenderContext.SetBlendingEnabled(false);
+ theRenderContext.SetDepthWriteEnabled(opaqueDepthWrite);
+ SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
SScopedLightsListScope lightsScope(m_Lights, m_LightDirections, m_SourceLightDirections,
theObject.m_ScopedLights);
- SetShaderFeature(m_CGLightingFeatureName, m_Lights.empty() == false);
+
+ if (theObject.m_RenderableFlags.hasAlphaTest())
+ m_Renderer.setAlphaTest(true, 1.0f, -1.0f + (1.0f / 255.0f));
+ else
+ m_Renderer.setAlphaTest(false, 1.0f, 1.0f);
+
inRenderFn(*this, theObject, theCameraProps, GetShaderFeatureSet(), indexLight,
inCamera);
}
+ }
- m_Renderer.setAlphaTest(true, -1.0f, 1.0f);
- // transparent parts of transparent objects
- // does not render objects without alpha test enabled so
- // we need another pass without alpha test
- renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
- indexLight, inCamera, theFB);
-
+ {
+ QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
+ "LayerRenderData: Render transparent pass")
m_Renderer.setAlphaTest(false, 1.0, 1.0);
- // transparent objects without alpha test
- renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableTransparentDepthWrite,
- indexLight, inCamera, theFB);
+ renderTransparentObjectsPass(inRenderFn, inEnableBlending, inEnableDepthWrite,
+ inEnableTransparentDepthWrite, indexLight, inCamera, theFB);
}
+}
void SLayerRenderData::Render(CResourceFrameBuffer *theFB)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::Render")
+ "LayerRenderData: Render")
if (m_Camera == NULL)
return;
@@ -1217,7 +1359,7 @@ namespace render {
theRenderContext.SetDepthTestEnabled(false);
theRenderContext.SetDepthWriteEnabled(false);
}
- BlendAdvancedEquationSwFallback(m_AdvancedBlendDrawTexture, m_LayerTexture, advancedMode);
+ BlendAdvancedEquationSwFallback(m_AdvancedBlendDrawTexture, m_LayerTexture[getCameraIndex()], advancedMode);
theRenderContext.SetRenderTarget(*theFB);
// setup read target
theRenderContext.SetReadTarget(m_AdvancedModeBlendFB);
@@ -1293,6 +1435,12 @@ namespace render {
CRegisteredString depthPassStr;
+ int SLayerRenderData::getCameraIndex() const
+ {
+ StereoViews::Enum stereoView = m_Renderer.GetQt3DSContext().GetStereoView();
+ return (stereoView == StereoViews::Right) ? 1 : 0;
+ }
+
// Render this layer's data to a texture. Required if we have any effects,
// prog AA, or if forced.
void SLayerRenderData::RenderToTexture()
@@ -1300,7 +1448,7 @@ namespace render {
QT3DS_ASSERT(m_LayerPrepResult->m_Flags.ShouldRenderToTexture());
SLayerRenderPreparationResult &thePrepResult(*m_LayerPrepResult);
NVRenderContext &theRenderContext(m_Renderer.GetContext());
- QSize theLayerTextureDimensions = thePrepResult.GetTextureDimensions();
+ QSize theLayerTextureDimensions(thePrepResult.GetTextureDimensions());
QSize theLayerOriginalTextureDimensions = theLayerTextureDimensions;
NVRenderTextureFormats::Enum DepthTextureFormat = NVRenderTextureFormats::Depth24Stencil8;
NVRenderTextureFormats::Enum ColorTextureFormat = NVRenderTextureFormats::RGBA8;
@@ -1332,13 +1480,14 @@ namespace render {
// progressive AA algorithm.
if (thePrepResult.m_Flags.WasLayerDataDirty()
|| thePrepResult.m_Flags.WasDirty()
+ || (getCameraIndex() == 1 && (m_LeftFlags.WasLayerDataDirty() || m_LeftFlags.WasDirty()))
|| m_Renderer.IsLayerCachingEnabled() == false) {
m_ProgressiveAAPassIndex = 0;
m_NonDirtyTemporalAAPassIndex = 0;
needsRender = true;
}
- CResourceTexture2D *renderColorTexture = &m_LayerTexture;
+ CResourceTexture2D *renderColorTexture = &m_LayerTexture[getCameraIndex()];
CResourceTexture2D *renderPrepassDepthTexture = &m_LayerPrepassDepthTexture;
CResourceTexture2D *renderWidgetTexture = &m_LayerWidgetTexture;
NVRenderContextScopedProperty<bool> __multisampleEnabled(
@@ -1356,7 +1505,7 @@ namespace render {
QT3DSU32 maxTemporalPassIndex = m_Layer.m_TemporalAAEnabled ? 2 : 0;
// If all the dimensions match then we do not have to re-render the layer.
- if (m_LayerTexture.TextureMatches(theLayerTextureDimensions.width(),
+ if (m_LayerTexture[getCameraIndex()].TextureMatches(theLayerTextureDimensions.width(),
theLayerTextureDimensions.height(), ColorTextureFormat)
&& (!thePrepResult.m_Flags.RequiresDepthTexture()
|| m_LayerDepthTexture.TextureMatches(theLayerTextureDimensions.width(),
@@ -1432,19 +1581,21 @@ namespace render {
if (isProgressiveAABlendPass || isTemporalAABlendPass) {
theBlendShader = m_Renderer.GetLayerProgAABlendShader();
if (theBlendShader) {
- m_LayerTexture.EnsureTexture(theLayerOriginalTextureDimensions.width(),
+ m_LayerTexture[getCameraIndex()].EnsureTexture(theLayerOriginalTextureDimensions.width(),
theLayerOriginalTextureDimensions.height(),
ColorTextureFormat);
QT3DSVec2 theVertexOffsets;
if (isProgressiveAABlendPass) {
- theLastLayerTexture.StealTexture(m_LayerTexture);
+ theLastLayerTexture.StealTexture(m_LayerTexture[getCameraIndex()]);
aaFactorIndex = (m_ProgressiveAAPassIndex - 1);
theVertexOffsets = s_VertexOffsets[aaFactorIndex];
} else {
- if (temporalAATexture.GetTexture())
- theLastLayerTexture.StealTexture(temporalAATexture);
- else if (hadLayerTexture)
- theLastLayerTexture.StealTexture(m_LayerTexture);
+ if (hadLayerTexture) {
+ if (temporalAATexture.GetTexture())
+ theLastLayerTexture.StealTexture(temporalAATexture);
+ else
+ theLastLayerTexture.StealTexture(m_LayerTexture[getCameraIndex()]);
+ }
theVertexOffsets = s_TemporalVertexOffsets[m_TemporalAAPassIndex];
++m_TemporalAAPassIndex;
@@ -1531,11 +1682,26 @@ namespace render {
// to that frame buffer.
theFB.EnsureFrameBuffer();
- bool hasDepthObjects = m_OpaqueObjects.size() > 0 || m_TransparentObjects.size() > 0;
+ bool hasDepthObjects = m_OpaqueObjects.size() > 0 || m_TransparentObjects.size() > 0
+ || m_GroupObjects.size() > 0;
bool requiresDepthStencilBuffer =
hasDepthObjects || thePrepResult.m_Flags.RequiresStencilBuffer();
NVRenderRect theNewViewport(0, 0, theLayerTextureDimensions.width(),
theLayerTextureDimensions.height());
+
+ if (m_Layer.m_DynamicResize && theLayerOriginalTextureDimensions.width() != 0) {
+ // With dynamic resize the viewport should behave like it just crops the full layer
+ // So a special viewport has to be calculated that keeps the original object sizes
+ float ratio = theLayerTextureDimensions.width()
+ / theLayerOriginalTextureDimensions.width();
+ auto originalLayerViewport = thePrepResult.getOriginalLayerToPresentationViewport();
+ auto layerViewport = thePrepResult.GetLayerToPresentationViewport();
+ theNewViewport = NVRenderRect((-layerViewport.m_X + originalLayerViewport.m_X) * ratio,
+ (-layerViewport.m_Y + originalLayerViewport.m_Y) * ratio,
+ originalLayerViewport.m_Width * ratio,
+ originalLayerViewport.m_Height * ratio);
+ }
+
{
theRenderContext.SetRenderTarget(theFB);
NVRenderContextScopedProperty<NVRenderRect> __viewport(
@@ -1630,6 +1796,9 @@ namespace render {
// will do this.
StartProfiling("Render pass", false);
Render(&theFB);
+
+ if (m_SignalProxy) // Editor does not have signal proxy, and this signal is not needed
+ Q_EMIT m_SignalProxy->SigFrameDraw();
// Debug measure to view the depth map to ensure we're rendering it correctly.
//if (m_Layer.m_TemporalAAEnabled) {
// RenderFakeDepthMapPass(m_ShadowMapManager->GetShadowMapEntry(0)->m_DepthMap,
@@ -1644,7 +1813,7 @@ namespace render {
if (m_Layer.m_MultisampleAAMode != AAModeValues::SSAA) {
// Resolve the FBO to the layer texture
CRendererUtil::ResolveMutisampleFBOColorOnly(
- theResourceManager, m_LayerTexture, theRenderContext,
+ theResourceManager, m_LayerTexture[getCameraIndex()], theRenderContext,
theLayerTextureDimensions.width(), theLayerTextureDimensions.height(),
ColorTextureFormat, *theFB);
@@ -1652,7 +1821,7 @@ namespace render {
} else {
// Resolve the FBO to the layer texture
CRendererUtil::ResolveSSAAFBOColorOnly(
- theResourceManager, m_LayerTexture,
+ theResourceManager, m_LayerTexture[getCameraIndex()],
theLayerOriginalTextureDimensions.width(),
theLayerOriginalTextureDimensions.height(), theRenderContext,
theLayerTextureDimensions.width(), theLayerTextureDimensions.height(),
@@ -1700,18 +1869,18 @@ namespace render {
theRenderContext.SetCullingEnabled(false);
theRenderContext.SetActiveShader(theBlendShader->m_Shader);
theBlendShader->m_AccumSampler.Set(theLastLayerTexture);
- theBlendShader->m_LastFrame.Set(m_LayerTexture);
+ theBlendShader->m_LastFrame.Set(m_LayerTexture[getCameraIndex()]);
theBlendShader->m_BlendFactors.Set(theBlendFactors);
m_Renderer.RenderQuad();
theFB->Attach(NVRenderFrameBufferAttachments::Color0,
qt3ds::render::NVRenderTextureOrRenderBuffer());
if (isTemporalAABlendPass)
- temporalAATexture.StealTexture(m_LayerTexture);
- m_LayerTexture.StealTexture(targetTexture);
+ temporalAATexture.StealTexture(m_LayerTexture[getCameraIndex()]);
+ m_LayerTexture[getCameraIndex()].StealTexture(targetTexture);
}
- m_LayerTexture->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
- m_LayerTexture->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
+ m_LayerTexture[getCameraIndex()]->SetMinFilter(NVRenderTextureMinifyingOp::Linear);
+ m_LayerTexture[getCameraIndex()]->SetMagFilter(NVRenderTextureMagnifyingOp::Linear);
// Don't remember why needs widget texture is false here.
// Should have commented why progAA plus widgets is a fail.
@@ -1734,6 +1903,8 @@ namespace render {
qt3ds::render::NVRenderTextureOrRenderBuffer(), thFboAttachTarget);
// Let natural scoping rules destroy the other stuff.
}
+ if (m_Layer.m_DynamicResize)
+ theResourceManager.DestroyFreeSizedResources();
}
void SLayerRenderData::ApplyLayerPostEffects()
@@ -1749,10 +1920,10 @@ namespace render {
}
}
if (!effectsActive || !m_Camera) {
- if (m_LayerCachedTexture) {
+ if (m_LayerCachedTexture[getCameraIndex()]) {
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
- theResourceManager.Release(*m_LayerCachedTexture);
- m_LayerCachedTexture = NULL;
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = NULL;
}
return;
}
@@ -1760,14 +1931,24 @@ namespace render {
IEffectSystem &theEffectSystem(m_Renderer.GetQt3DSContext().GetEffectSystem());
IResourceManager &theResourceManager(m_Renderer.GetQt3DSContext().GetResourceManager());
// we use the non MSAA buffer for the effect
- NVRenderTexture2D *theLayerColorTexture = m_LayerTexture;
+ NVRenderTexture2D *theLayerColorTexture = m_LayerTexture[getCameraIndex()];
NVRenderTexture2D *theLayerDepthTexture = m_LayerDepthTexture;
- if (!m_LayerCachedTexture) {
+ if (m_LayerCachedTexture[getCameraIndex()]) {
+ STextureDetails details(theLayerColorTexture->GetTextureDetails());
+ STextureDetails cachedDetails(m_LayerCachedTexture[getCameraIndex()]->GetTextureDetails());
+ if (cachedDetails.m_Width != details.m_Width
+ || cachedDetails.m_Height != details.m_Height) {
+ theResourceManager.Release(*m_LayerCachedTexture[getCameraIndex()]);
+ m_LayerCachedTexture[getCameraIndex()] = nullptr;
+ }
+ }
+
+ if (!m_LayerCachedTexture[getCameraIndex()]) {
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,
+ m_LayerCachedTexture[getCameraIndex()] = theResourceManager.AllocateTexture2D(finalWidth, finalHeight,
details.m_Format);
}
@@ -1777,7 +1958,7 @@ namespace render {
if (theEffect->m_Flags.IsActive()) {
NVRenderTexture2D *targetTexture = nullptr;
if (theEffect == lastEffect)
- targetTexture = m_LayerCachedTexture;
+ targetTexture = m_LayerCachedTexture[getCameraIndex()];
StartProfiling(theEffect->m_ClassName, false);
@@ -1819,13 +2000,13 @@ namespace render {
void SLayerRenderData::RunnableRenderToViewport(qt3ds::render::NVRenderFrameBuffer *theFB)
{
// If we have an effect, an opaque object, or any transparent objects that aren't completely
- // transparent
- // or an offscreen renderer or a layer widget texture
+ // transparent or an offscreen renderer or a layer widget texture
// Then we can't possible affect the resulting render target.
- bool needsToRender = m_Layer.m_FirstEffect != NULL || m_OpaqueObjects.empty() == false
+ bool needsToRender = m_Layer.m_FirstEffect || !m_OpaqueObjects.empty()
|| AnyCompletelyNonTransparentObjects(m_TransparentObjects) || GetOffscreenRenderer()
|| m_LayerWidgetTexture || m_BoundingRectColor.hasValue()
- || m_Layer.m_Background == LayerBackground::Color;
+ || m_Layer.m_Background == LayerBackground::Color
+ || !m_GroupObjects.empty();
if (needsToRender == false)
return;
@@ -1872,7 +2053,7 @@ namespace render {
// The render graph should have taken care of the render to texture step.
#ifdef QT3DS_CACHED_POST_EFFECT
NVRenderTexture2D *theLayerColorTexture =
- (m_LayerCachedTexture) ? m_LayerCachedTexture : m_LayerTexture;
+ (m_LayerCachedTexture[getCameraIndex()]) ? m_LayerCachedTexture[getCameraIndex()] : m_LayerTexture[getCameraIndex()];
#else
// Then render all but the last effect
IEffectSystem &theEffectSystem(m_Renderer.GetQt3DSContext().GetEffectSystem());
@@ -1913,10 +2094,12 @@ namespace render {
// transform.
QT3DSMat44 theFinalMVP(QT3DSMat44::createIdentity());
SCamera theTempCamera;
+ // When layer & scene are part of subpresentation, ignore stereoscopic viewport adjustments
+ bool noStereo = m_Layer.m_Scene && m_Layer.m_Scene->m_IsSubPresentationScene;
NVRenderRect theLayerViewport(
- thePrepResult.GetLayerToPresentationViewport().ToIntegerRect());
+ thePrepResult.GetLayerToPresentationViewport(noStereo).ToIntegerRect());
NVRenderRect theLayerClip(
- thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect());
+ thePrepResult.GetLayerToPresentationScissorRect(noStereo).ToIntegerRect());
{
QT3DSMat33 ignored;
@@ -2214,7 +2397,7 @@ namespace render {
void SLayerRenderData::AddLayerRenderStep()
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::AddLayerRenderStep")
+ "LayerRenderData: AddLayerRenderStep")
QT3DS_ASSERT(m_Camera);
if (!m_Camera)
return;
@@ -2227,13 +2410,13 @@ namespace render {
QSize(theCurrentViewport.m_Width, theCurrentViewport.m_Height));
}
- void SLayerRenderData::PrepareForRender()
+ bool SLayerRenderData::PrepareForRender()
{
// When we render to the scene itself (as opposed to an offscreen buffer somewhere)
// then we use the MVP of the layer somewhat.
NVRenderRect theViewport = m_Renderer.GetQt3DSContext().GetRenderList().GetViewport();
- PrepareForRender(
- QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height));
+ return PrepareForRender(
+ QSize((QT3DSU32)theViewport.m_Width, (QT3DSU32)theViewport.m_Height));
}
void SLayerRenderData::ResetForFrame()
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
index 0f0a838..623e8b2 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderData.h
@@ -33,6 +33,7 @@
#include "Qt3DSRender.h"
#include "Qt3DSRendererImplLayerRenderPreparationData.h"
#include "Qt3DSRenderResourceBufferObjects.h"
+#include "Qt3DSRuntimeView.h"
namespace qt3ds {
namespace render {
@@ -52,7 +53,7 @@ struct AdvancedBlendModes
// Layers can be rendered offscreen for many reasons; effects, progressive aa,
// or just because a flag forces it. If they are rendered offscreen we can then
// cache the result so we don't render the layer again if it isn't dirty.
- CResourceTexture2D m_LayerTexture;
+ CResourceTexture2D m_LayerTexture[2];
// Multiple temporal AA textures for stereoscopic needs.
// First used for mono/left view, second for right view.
CResourceTexture2D m_TemporalAATexture[2];
@@ -66,7 +67,7 @@ struct AdvancedBlendModes
CResourceTexture2D m_LayerMultisamplePrepassDepthTexture;
CResourceTexture2D m_LayerMultisampleWidgetTexture;
// the texture contains the render result inclusive post effects
- NVRenderTexture2D *m_LayerCachedTexture;
+ NVRenderTexture2D *m_LayerCachedTexture[2];
NVRenderTexture2D *m_AdvancedBlendDrawTexture;
NVRenderTexture2D *m_AdvancedBlendBlendTexture;
@@ -97,15 +98,19 @@ struct AdvancedBlendModes
NVRenderTextureFormats::Enum m_DepthBufferFormat;
QSize m_previousDimensions;
+ QRuntimeViewSignalProxy *m_SignalProxy;
+ SLayerRenderPreparationResultFlags m_LeftFlags;
+
+ int getCameraIndex() const;
SLayerRenderData(SLayer &inLayer, Qt3DSRendererImpl &inRenderer);
virtual ~SLayerRenderData();
- void PrepareForRender();
+ bool PrepareForRender();
// Internal Call
- void PrepareForRender(const QSize &inViewportDimensions) override;
+ bool PrepareForRender(const QSize &inViewportDimensions) override;
NVRenderTextureFormats::Enum GetDepthBufferFormat();
NVRenderFrameBufferAttachments::Enum
@@ -125,6 +130,10 @@ struct AdvancedBlendModes
void Render(CResourceFrameBuffer *theFB = NULL);
void ResetForFrame() override;
+ void renderOrderedGroup(SRenderableObject &theObject, TRenderRenderableFunction inRenderFn,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite, QT3DSU32 indexLight,
+ const SCamera &inCamera, CResourceFrameBuffer *theFB);
void CreateGpuProfiler();
void StartProfiling(CRegisteredString &nameID, bool sync);
@@ -179,7 +188,8 @@ struct AdvancedBlendModes
CResourceFrameBuffer *theFB);
#endif
void renderTransparentObjectsPass(TRenderRenderableFunction inRenderFn,
- bool inEnableBlending, bool inEnableTransparentDepthWrite,
+ bool inEnableBlending, bool inEnableDepthWrite,
+ bool inEnableTransparentDepthWrite,
QT3DSU32 indexLight, const SCamera &inCamera,
CResourceFrameBuffer *theFB);
};
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
index 4dae3f9..f75a673 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.cpp
@@ -70,8 +70,8 @@ QT3DSVec2 ToRectRelativeCoords(const QT3DSVec2 &inCoords, const NVRenderRectF &i
SLayerRenderHelper::SLayerRenderHelper()
: m_Layer(nullptr)
, m_Camera(nullptr)
- , m_CameraLeftEye(nullptr)
- , m_CameraRightEye(nullptr)
+ , m_CameraLeftEye()
+ , m_CameraRightEye()
, m_Offscreen(false)
{
}
@@ -84,19 +84,21 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
qt3ds::render::StereoModes::Enum inStereoMode,
qt3ds::render::StereoViews::Enum inStereoView,
double inStereoEyeSeparation,
+ double inStereoEyeRotation,
qt3ds::QT3DSVec2 inScaleFactor)
: m_PresentationViewport(inPresentationViewport)
, m_PresentationScissor(inPresentationScissor)
, m_PresentationDesignDimensions(inPresentationDesignDimensions)
, m_Layer(&inLayer)
, m_Camera(nullptr)
- , m_CameraLeftEye(nullptr)
- , m_CameraRightEye(nullptr)
+ , m_CameraLeftEye()
+ , m_CameraRightEye()
, m_Offscreen(inOffscreen)
, m_ScaleMode(inScaleMode)
, m_StereoMode(inStereoMode)
, m_StereoView(inStereoView)
, m_StereoEyeSeparation(QT3DSF32(inStereoEyeSeparation))
+ , m_StereoEyeRotation(QT3DSF32(inStereoEyeRotation))
, m_ScaleFactor(inScaleFactor)
{
{
@@ -178,9 +180,9 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
- // Now force the viewport to be a multiple of four in width and height. This is because
+ // Now force the viewport to be a multiple of four in width and height. This is because
// when rendering to a texture we have to respect this and not forcing it causes scaling issues
- // that are noticeable especially in situations where customers are using text and such.
+ // that are noticeable especially in situations where customers are using text.
QT3DSF32 originalWidth = m_Viewport.m_Width;
QT3DSF32 originalHeight = m_Viewport.m_Height;
@@ -191,6 +193,7 @@ SLayerRenderHelper::SLayerRenderHelper(const NVRenderRectF &inPresentationViewpo
m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+ m_originalViewport = m_Viewport;
m_Scissor = m_Viewport;
m_Scissor.EnsureInBounds(inPresentationScissor);
QT3DS_ASSERT(m_Scissor.m_Width >= 0.0f);
@@ -206,8 +209,11 @@ NVRenderRectF SLayerRenderHelper::GetLayerRenderViewport() const
return m_Viewport;
}
-NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport() const
+NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport(bool noStereo) const
{
+ if (noStereo)
+ return m_Viewport;
+
if (m_StereoMode == StereoModes::LeftRight) {
if (m_StereoView == StereoViews::Left) {
return NVRenderRectF(m_Viewport.m_X, m_Viewport.m_Y, m_Viewport.m_Width/2,
@@ -230,8 +236,11 @@ NVRenderRectF SLayerRenderHelper::GetLayerToPresentationViewport() const
return m_Viewport;
}
-NVRenderRectF SLayerRenderHelper::GetLayerToPresentationScissorRect() const
+NVRenderRectF SLayerRenderHelper::GetLayerToPresentationScissorRect(bool noStereo) const
{
+ if (noStereo)
+ return m_Scissor;
+
if (m_StereoMode == StereoModes::LeftRight) {
if (m_StereoView == StereoViews::Left) {
return NVRenderRectF(m_Scissor.m_X, m_Scissor.m_Y,
@@ -265,9 +274,9 @@ QSize SLayerRenderHelper::GetTextureDimensions() const
SCamera *SLayerRenderHelper::GetCamera() {
if (m_StereoView == StereoViews::Left)
- return m_CameraLeftEye;
+ return &m_CameraLeftEye;
if (m_StereoView == StereoViews::Right)
- return m_CameraRightEye;
+ return &m_CameraRightEye;
return m_Camera;
}
@@ -275,8 +284,10 @@ SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera
{
m_Camera = &inCamera;
- if (isStereoscopic())
+ if (isStereoscopic()) {
+ m_Camera->AddChild(*GetCamera());
adjustCameraStereoSeparation();
+ }
NVRenderRectF rect = GetLayerRenderViewport();
if (m_ScaleMode == ScaleModes::FitSelected) {
@@ -286,10 +297,13 @@ SCameraGlobalCalculationResult SLayerRenderHelper::SetupCameraForRender(SCamera
(QT3DSF32)(ITextRenderer::NextMultipleOf4((QT3DSU32)(rect.m_Height / m_ScaleFactor.y)));
}
// Always calculate main camera variables
- if (isStereoscopic())
- m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
- // Return current camera variables
- return GetCamera()->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ auto ret = m_Camera->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ if (isStereoscopic()) {
+ GetCamera()->CalculateGlobalVariables(rect, m_PresentationDesignDimensions);
+ m_Camera->RemoveChild(*GetCamera());
+ }
+
+ return ret;
}
Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMouseCoords,
@@ -299,7 +313,16 @@ Option<QT3DSVec2> SLayerRenderHelper::GetLayerMouseCoords(const QT3DSVec2 &inMou
// First invert the y so we are dealing with numbers in a normal coordinate space.
// Second, move into our layer's coordinate space
QT3DSVec2 correctCoords(inMouseCoords.x, inWindowDimensions.y - inMouseCoords.y);
- QT3DSVec2 theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+ QT3DSVec2 theLocalMouse;
+
+ if (m_Layer->m_DynamicResize) {
+ float widthRatio = m_Viewport.m_Width / m_originalViewport.m_Width;
+ float heightRatio = m_Viewport.m_Height / m_originalViewport.m_Height;
+ theLocalMouse = m_originalViewport.ToRectRelative(correctCoords);
+ theLocalMouse = QT3DSVec2(theLocalMouse.x * widthRatio, theLocalMouse.y * heightRatio);
+ } else {
+ theLocalMouse = m_Viewport.ToRectRelative(correctCoords);
+ }
QT3DSF32 theRenderRectWidth = m_Viewport.m_Width;
QT3DSF32 theRenderRectHeight = m_Viewport.m_Height;
@@ -341,8 +364,32 @@ bool SLayerRenderHelper::isStereoscopic() const
return m_StereoMode != StereoModes::Mono;
}
-void SLayerRenderHelper::copyCameraProperties(SCamera *sourceCamera,
- SCamera *destinationCamera)
+void SLayerRenderHelper::setViewport(const NVRenderRectF &viewport)
+{
+ m_Viewport = viewport;
+ m_Viewport.m_Width = NVMax(1.0f, m_Viewport.m_Width);
+ m_Viewport.m_Height = NVMax(1.0f, m_Viewport.m_Height);
+ // Now force the viewport to be a multiple of four in width and height. This is because
+ // when rendering to a texture we have to respect this and not forcing it causes scaling issues
+ // that are noticeable especially in situations where customers are using text.
+ QT3DSF32 originalWidth = m_Viewport.m_Width;
+ QT3DSF32 originalHeight = m_Viewport.m_Height;
+
+ m_Viewport.m_Width = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Width);
+ m_Viewport.m_Height = (QT3DSF32)ITextRenderer::NextMultipleOf4((QT3DSU32)m_Viewport.m_Height);
+
+ // Now fudge the offsets to account for this slight difference
+ m_Viewport.m_X += (originalWidth - m_Viewport.m_Width) / 2.0f;
+ m_Viewport.m_Y += (originalHeight - m_Viewport.m_Height) / 2.0f;
+}
+
+NVRenderRectF SLayerRenderHelper::getOriginalLayerToPresentationViewport() const
+{
+ return m_originalViewport;
+}
+
+void SLayerRenderHelper::copyCameraStereoProperties(SCamera *sourceCamera,
+ SCamera *destinationCamera)
{
if (!sourceCamera || !destinationCamera)
return;
@@ -360,33 +407,27 @@ void SLayerRenderHelper::copyCameraProperties(SCamera *sourceCamera,
destinationCamera->m_Pivot = sourceCamera->m_Pivot;
destinationCamera->m_Scale = sourceCamera->m_Scale;
destinationCamera->m_DFSIndex = sourceCamera->m_DFSIndex;
- destinationCamera->m_Position = sourceCamera->m_Position;
- destinationCamera->m_Rotation = sourceCamera->m_Rotation;
- destinationCamera->m_UserData = sourceCamera->m_UserData;
- destinationCamera->m_LocalOpacity = sourceCamera->m_LocalOpacity;
- destinationCamera->m_GlobalOpacity = sourceCamera->m_GlobalOpacity;
destinationCamera->m_RotationOrder = sourceCamera->m_RotationOrder;
- destinationCamera->m_LocalTransform = sourceCamera->m_LocalTransform;
- destinationCamera->m_GlobalTransform = sourceCamera->m_GlobalTransform;
}
void SLayerRenderHelper::adjustCameraStereoSeparation()
{
- if (!m_CameraLeftEye)
- m_CameraLeftEye = new SCamera();
- if (!m_CameraRightEye)
- m_CameraRightEye = new SCamera();
-
// Copy m_Camera properties into left & right cameras
- copyCameraProperties(m_Camera, m_CameraLeftEye);
- copyCameraProperties(m_Camera, m_CameraRightEye);
+ copyCameraStereoProperties(m_Camera, &m_CameraLeftEye);
+ copyCameraStereoProperties(m_Camera, &m_CameraRightEye);
// Adjust left & right camera positions by eye separation
- m_CameraLeftEye->m_Position.x -= m_StereoEyeSeparation;
- m_CameraLeftEye->m_Flags.SetTransformDirty(true);
- m_CameraRightEye->m_Position.x += m_StereoEyeSeparation;
- m_CameraRightEye->m_Flags.SetTransformDirty(true);
-
- m_CameraLeftEye->MarkDirty();
- m_CameraRightEye->MarkDirty();
+ QT3DSVec3 eyeMove(m_StereoEyeSeparation, 0, 0);
+ m_CameraLeftEye.m_Position = -eyeMove;
+ m_CameraLeftEye.m_Flags.SetTransformDirty(true);
+ m_CameraRightEye.m_Position = eyeMove;
+ m_CameraRightEye.m_Flags.SetTransformDirty(true);
+
+ // Adjust left & right camera rotations
+ QT3DSVec3 eyeRotation(0, m_StereoEyeRotation, 0);
+ m_CameraLeftEye.m_Rotation = eyeRotation;
+ m_CameraRightEye.m_Rotation = -eyeRotation;
+
+ m_CameraLeftEye.MarkDirty();
+ m_CameraRightEye.MarkDirty();
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
index 19fd3f5..2c64569 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderHelper.h
@@ -60,10 +60,11 @@ namespace render {
QT3DSVec2 m_PresentationDesignDimensions;
SLayer *m_Layer;
SCamera *m_Camera;
- SCamera *m_CameraLeftEye;
- SCamera *m_CameraRightEye;
+ SCamera m_CameraLeftEye;
+ SCamera m_CameraRightEye;
bool m_Offscreen;
+ NVRenderRectF m_originalViewport;
NVRenderRectF m_Viewport;
NVRenderRectF m_Scissor;
@@ -72,6 +73,7 @@ namespace render {
StereoModes::Enum m_StereoMode = StereoModes::Mono;
StereoViews::Enum m_StereoView = StereoViews::Mono;
QT3DSF32 m_StereoEyeSeparation = 0.4f;
+ QT3DSF32 m_StereoEyeRotation = 0.0f;
QT3DSVec2 m_ScaleFactor;
@@ -85,6 +87,7 @@ namespace render {
qt3ds::render::StereoModes::Enum inStereoMode,
qt3ds::render::StereoViews::Enum inStereoView,
double inStereoEyeSeparation,
+ double inStereoEyeRotation,
qt3ds::QT3DSVec2 inScaleFactor);
NVRenderRectF GetPresentationViewport() const { return m_PresentationViewport; }
@@ -102,13 +105,18 @@ namespace render {
// Get/set eye (camera) separation.
QT3DSF32 getEyeSeparation() const { return m_StereoEyeSeparation; }
void setEyeSeparation(QT3DSF32 separation) { m_StereoEyeSeparation = separation; }
+ // Get/set eye (camera) rotation.
+ QT3DSF32 getEyeRotation() const { return m_StereoEyeRotation; }
+ void setEyeRotation(QT3DSF32 rotation) { m_StereoEyeRotation = rotation; }
+ void setViewport(const NVRenderRectF &viewport);
// Does not differ whether offscreen or not, simply states how this layer maps to the
// presentation
- NVRenderRectF GetLayerToPresentationViewport() const;
+ NVRenderRectF getOriginalLayerToPresentationViewport() const;
+ NVRenderRectF GetLayerToPresentationViewport(bool noStereo = false) const;
// Does not differ whether offscreen or not, scissor rect of how this layer maps to
// presentation.
- NVRenderRectF GetLayerToPresentationScissorRect() const;
+ NVRenderRectF GetLayerToPresentationScissorRect(bool noStereo = false) const;
QSize GetTextureDimensions() const;
@@ -130,7 +138,7 @@ namespace render {
// different than the layer to presentation viewport.
NVRenderRectF GetLayerRenderViewport() const;
- void copyCameraProperties(SCamera *sourceCamera, SCamera *destinationCamera);
+ void copyCameraStereoProperties(SCamera *sourceCamera, SCamera *destinationCamera);
void adjustCameraStereoSeparation();
};
}
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
index df60f64..c8c287c 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp
@@ -72,18 +72,29 @@ namespace render {
namespace {
void MaybeQueueNodeForRender(SNode &inNode, nvvector<SRenderableNodeEntry> &outRenderables,
- nvvector<SNode *> &outCamerasAndLights, QT3DSU32 &ioDFSIndex)
+ nvvector<SRenderableNodeEntry> &outGroups,
+ nvvector<SNode *> &outCamerasAndLights, QT3DSU32 &ioDFSIndex,
+ QT3DSU32 groupNode = 0)
{
++ioDFSIndex;
inNode.m_DFSIndex = ioDFSIndex;
- if (GraphObjectTypes::IsRenderableType(inNode.m_Type))
+ inNode.m_GroupIndex = groupNode;
+ if (GraphObjectTypes::IsRenderableType(inNode.m_Type)) {
outRenderables.push_back(inNode);
- else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type))
+ } else if (GraphObjectTypes::IsLightCameraType(inNode.m_Type)) {
outCamerasAndLights.push_back(&inNode);
+ } else if (GraphObjectTypes::IsNodeType(inNode.m_Type) && inNode.m_ordered
+ && !groupNode) {
+ outGroups.push_back(inNode);
+ groupNode = outGroups.size();
+ inNode.m_GroupIndex = groupNode;
+ }
for (SNode *theChild = inNode.m_FirstChild; theChild != NULL;
- theChild = theChild->m_NextSibling)
- MaybeQueueNodeForRender(*theChild, outRenderables, outCamerasAndLights, ioDFSIndex);
+ theChild = theChild->m_NextSibling) {
+ MaybeQueueNodeForRender(*theChild, outRenderables, outGroups, outCamerasAndLights,
+ ioDFSIndex, groupNode);
+ }
}
bool HasValidLightProbe(SImage *inLightProbeImage)
@@ -113,6 +124,8 @@ namespace render {
"SLayerRenderPreparationData::m_RenderableNodes"))
, m_RenderableNodes(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_RenderableNodes")
+ , m_GroupNodes(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_GroupNodes")
, m_LightToNodeMap(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_LightToNodeMap")
, m_CamerasAndLights(inRenderer.GetContext().GetAllocator(),
@@ -123,6 +136,8 @@ namespace render {
"SLayerRenderPreparationData::m_OpaqueObjects")
, m_TransparentObjects(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_TransparentObjects")
+ , m_GroupObjects(inRenderer.GetContext().GetAllocator(),
+ "SLayerRenderPreparationData::m_GroupObjects")
, m_RenderedOpaqueObjects(inRenderer.GetContext().GetAllocator(),
"SLayerRenderPreparationData::m_RenderedOpaqueObjects")
, m_RenderedTransparentObjects(inRenderer.GetContext().GetAllocator(),
@@ -140,6 +155,7 @@ namespace render {
, m_FeaturesDirty(true)
, m_FeatureSetHash(0)
, m_TooManyLightsError(false)
+ , m_StereoMode(StereoModes::Mono)
{
}
@@ -246,10 +262,12 @@ namespace render {
{
if (m_RenderedOpaqueObjects.empty() == false || m_Camera == NULL)
return m_RenderedOpaqueObjects;
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() && m_OpaqueObjects.empty() == false) {
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest()
+ && (!m_OpaqueObjects.empty() || !m_GroupObjects.empty())) {
QT3DSVec3 theCameraDirection(GetCameraDirection());
QT3DSVec3 theCameraPosition = m_Camera->GetGlobalPos();
m_RenderedOpaqueObjects.assign(m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+
// Setup the object's sorting information
for (QT3DSU32 idx = 0, end = m_RenderedOpaqueObjects.size(); idx < end; ++idx) {
SRenderableObject &theInfo = *m_RenderedOpaqueObjects[idx];
@@ -273,10 +291,19 @@ namespace render {
m_RenderedTransparentObjects.assign(m_TransparentObjects.begin(),
m_TransparentObjects.end());
+ m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(), m_GroupObjects.begin(),
+ m_GroupObjects.end());
+
+ // Set position for group objects
+ for (int i = 0; i < m_GroupObjects.size(); i++)
+ static_cast<SOrderedGroupRenderable *>(m_GroupObjects[i])->update();
- if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false) {
m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(),
m_OpaqueObjects.begin(), m_OpaqueObjects.end());
+ m_RenderedTransparentObjects.insert(m_RenderedTransparentObjects.end(),
+ m_GroupObjects.begin(), m_GroupObjects.end());
+ }
if (m_RenderedTransparentObjects.empty() == false) {
QT3DSVec3 theCameraDirection(GetCameraDirection());
@@ -287,7 +314,11 @@ namespace render {
SRenderableObject &theInfo = *m_RenderedTransparentObjects[idx];
QT3DSVec3 difference = theInfo.m_WorldCenterPoint - theCameraPosition;
theInfo.m_CameraDistanceSq = difference.dot(theCameraDirection);
+
+ if (m_Layer.m_Flags.IsLayerEnableDepthTest() == false)
+ theInfo.m_RenderableFlags.setAlphaTest(0);
}
+
ForwardingAllocator alloc(m_Renderer.GetPerFrameAllocator(), "SortAllocations");
// render furthest to nearest.
eastl::merge_sort(m_RenderedTransparentObjects.begin(),
@@ -365,7 +396,8 @@ namespace render {
bool SLayerRenderPreparationData::PrepareTextForRender(
SText &inText, const QT3DSMat44 &inViewProjection,
- QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags)
+ QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags,
+ qt3ds::render::SOrderedGroupRenderable *group)
{
ITextTextureCache *theTextRenderer = m_Renderer.GetQt3DSContext().GetTextureCache();
if (theTextRenderer == nullptr && !IQt3DSRenderContextCore::distanceFieldEnabled())
@@ -424,8 +456,12 @@ namespace render {
// After preparation, do not push object back to queue if it is not
// active, because we prepare text elements regardless of their
// visibility (=active status).
- if (inText.m_Flags.IsGloballyActive())
- m_TransparentObjects.push_back(theRenderable);
+ if (inText.m_Flags.IsGloballyActive()) {
+ if (group)
+ group->m_renderables.push_back(theRenderable);
+ else
+ m_TransparentObjects.push_back(theRenderable);
+ }
}
return retval;
}
@@ -459,7 +495,8 @@ namespace render {
bool SLayerRenderPreparationData::PreparePathForRender(
SPath &inPath, const QT3DSMat44 &inViewProjection,
- const Option<SClippingFrustum> &inClipFrustum, SLayerRenderPreparationResultFlags &ioFlags)
+ const Option<SClippingFrustum> &inClipFrustum, SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group)
{
SRenderableObjectFlags theSharedFlags;
theSharedFlags.SetPickable(true);
@@ -603,7 +640,10 @@ namespace render {
IOffscreenRenderManager &theOffscreenRenderManager(
qt3dsContext.GetOffscreenRenderManager());
IRenderPluginManager &theRenderPluginManager(qt3dsContext.GetRenderPluginManager());
- if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager))
+ if (inImage.ClearDirty(bufferManager, theOffscreenRenderManager, theRenderPluginManager,
+ m_Layer.m_Scene->m_Presentation->m_preferKTX,
+ inImage.m_MappingMode == ImageMappingModes::LightProbe,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures))
ioFlags |= RenderPreparationResultFlagValues::Dirty;
// All objects with offscreen renderers are pickable so we can pass the pick through to the
@@ -790,7 +830,8 @@ namespace render {
// Enable alpha test, but only if the whole object opacity is full
// so parts of the object might be fully opaque
if (renderableFlags & RenderPreparationResultFlagValues::HasTransparency
- && subsetOpacity >= 1.0f && transparencyImagesHaveOpaquePixels) {
+ && subsetOpacity >= 1.0f && transparencyImagesHaveOpaquePixels
+ && theMaterial->m_BlendMode != DefaultMaterialBlendMode::Screen) {
m_Renderer.DefaultMaterialShaderKeyProperties()
.m_AlphaTestEnabled.SetValue(theGeneratedKey, true);
renderableFlags.setAlphaTest(true);
@@ -825,7 +866,10 @@ namespace render {
// If the custom material uses subpresentations, those have to be rendered before
// the custom material itself
- m_Renderer.GetQt3DSContext().GetCustomMaterialSystem().renderSubpresentations(inMaterial);
+ if (m_Renderer.GetQt3DSContext().GetCustomMaterialSystem()
+ .renderSubpresentations(inMaterial)) {
+ retval.m_Dirty = true;
+ }
// set wireframe mode
m_Renderer.DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
@@ -862,17 +906,17 @@ namespace render {
CHECK_IMAGE_AND_PREPARE(inMaterial.m_Lightmaps.m_LightmapShadow,
ImageMapTypes::LightmapShadow,
SShaderDefaultMaterialKeyProperties::LightmapShadow);
- if (inMaterial.m_imageMaps && inMaterial.m_imageMaps->size() > 0) {
- auto iter = inMaterial.m_imageMaps->begin();
- auto end = inMaterial.m_imageMaps->end();
+ if (inMaterial.m_images.size() > 0) {
+ auto iter = inMaterial.m_images.begin();
+ auto end = inMaterial.m_images.end();
for (; iter != end; iter++) {
- CHECK_IMAGE_AND_PREPARE(iter->second,
+ CHECK_IMAGE_AND_PREPARE(*iter,
ImageMapTypes::Unknown,
SShaderDefaultMaterialKeyProperties::ImageMapCount);
}
}
#undef CHECK_IMAGE_AND_PREPARE
-
+ retval.m_Dirty |= renderableFlags.IsDirty();
retval.m_FirstImage = firstImage;
if (retval.m_Dirty || alreadyDirty)
m_Renderer.addMaterialDirtyClear(&inMaterial);
@@ -881,7 +925,8 @@ namespace render {
bool SLayerRenderPreparationData::PrepareModelForRender(
SModel &inModel, const QT3DSMat44 &inViewProjection,
- const Option<SClippingFrustum> &inClipFrustum, TNodeLightEntryList &inScopedLights)
+ const Option<SClippingFrustum> &inClipFrustum, TNodeLightEntryList &inScopedLights,
+ SOrderedGroupRenderable *group)
{
IQt3DSRenderContext &qt3dsContext(m_Renderer.GetQt3DSContext());
IBufferManager &bufferManager = qt3dsContext.GetBufferManager();
@@ -1011,6 +1056,7 @@ namespace render {
subsetOpacity, subsetDirty));
SShaderDefaultMaterialKey theGeneratedKey = theMaterialPrepResult.m_MaterialKey;
subsetOpacity = theMaterialPrepResult.m_Opacity;
+ subsetDirty |= theMaterialPrepResult.m_Dirty;
SRenderableImage *firstImage(theMaterialPrepResult.m_FirstImage);
renderableFlags = theMaterialPrepResult.m_RenderableFlags;
@@ -1037,12 +1083,26 @@ namespace render {
theRenderableObject->m_ScopedLights = inScopedLights;
// set tessellation
theRenderableObject->m_TessellationMode = inModel.m_TessellationMode;
-
- if (theRenderableObject->m_RenderableFlags.HasTransparency()
- || theRenderableObject->m_RenderableFlags.HasRefraction()) {
- m_TransparentObjects.push_back(theRenderableObject);
+ bool transparentObject = theRenderableObject->m_RenderableFlags.HasTransparency()
+ || theRenderableObject->m_RenderableFlags.HasRefraction();
+ bool alphaTestObject = theRenderableObject->m_RenderableFlags.hasAlphaTest();
+
+ // Only put transparent object into ordered group if depth test is on
+ // Put object into both lists if it is alpha-test object
+ // object must have transparency on if it is alpha-test object
+ if (group && (!m_Layer.m_Flags.IsLayerEnableDepthTest() || transparentObject)) {
+ group->m_renderables.push_back(theRenderableObject);
+ if (alphaTestObject)
+ m_OpaqueObjects.push_back(theRenderableObject);
} else {
- m_OpaqueObjects.push_back(theRenderableObject);
+ if (transparentObject && alphaTestObject) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ m_OpaqueObjects.push_back(theRenderableObject);
+ } else if (transparentObject) {
+ m_TransparentObjects.push_back(theRenderableObject);
+ } else {
+ m_OpaqueObjects.push_back(theRenderableObject);
+ }
}
}
}
@@ -1055,24 +1115,43 @@ namespace render {
QT3DSF32 inTextScaleFactor, SLayerRenderPreparationResultFlags &ioFlags)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::PrepareRenderablesForRender")
+ "LayerRenderData: PrepareRenderablesForRender")
m_ViewProjection = inViewProjection;
QT3DSF32 theTextScaleFactor = inTextScaleFactor;
bool wasDataDirty = false;
bool hasTextRenderer
= m_Renderer.GetQt3DSContext().getDistanceFieldRenderer() != nullptr
|| m_Renderer.GetQt3DSContext().GetTextRenderer() != nullptr;
+ for (QT3DSU32 idx = 0, end = m_GroupNodes.size(); idx < end; ++idx) {
+ SRenderableNodeEntry &theNodeEntry(m_GroupNodes[idx]);
+ SRenderableObjectFlags flags;
+ QT3DSVec3 inWorldCenterPt;
+ QT3DSMat44 inGlobalTransform;
+ NVBounds3 inBounds;
+ SOrderedGroupRenderable *renderable
+ = RENDER_FRAME_NEW(SOrderedGroupRenderable)(
+ flags, inWorldCenterPt, inGlobalTransform, inBounds,
+ m_Renderer.GetPerFrameAllocator());
+ m_GroupObjects.push_back(renderable);
+ }
+
for (QT3DSU32 idx = 0, end = m_RenderableNodes.size(); idx < end; ++idx) {
SRenderableNodeEntry &theNodeEntry(m_RenderableNodes[idx]);
SNode *theNode = theNodeEntry.m_Node;
wasDataDirty = wasDataDirty || theNode->m_Flags.IsDirty();
+ SOrderedGroupRenderable *group = nullptr;
+ if (theNode->m_GroupIndex) {
+ group = static_cast<SOrderedGroupRenderable *>(
+ m_GroupObjects[theNode->m_GroupIndex - 1]);
+ }
+
switch (theNode->m_Type) {
case GraphObjectTypes::Model: {
SModel *theModel = static_cast<SModel *>(theNode);
theModel->CalculateGlobalVariables();
if (theModel->m_Flags.IsGloballyActive()) {
bool wasModelDirty = PrepareModelForRender(
- *theModel, inViewProjection, inClipFrustum, theNodeEntry.m_Lights);
+ *theModel, inViewProjection, inClipFrustum, theNodeEntry.m_Lights, group);
wasDataDirty = wasDataDirty || wasModelDirty;
}
} break;
@@ -1085,7 +1164,7 @@ namespace render {
// large delay for distance field text items becoming active
// mid-animation.
bool wasTextDirty = PrepareTextForRender(*theText, inViewProjection,
- theTextScaleFactor, ioFlags);
+ theTextScaleFactor, ioFlags, group);
wasDataDirty = wasDataDirty || wasTextDirty;
}
@@ -1095,7 +1174,8 @@ namespace render {
thePath->CalculateGlobalVariables();
if (thePath->m_Flags.IsGloballyActive()) {
bool wasPathDirty =
- PreparePathForRender(*thePath, inViewProjection, inClipFrustum, ioFlags);
+ PreparePathForRender(*thePath, inViewProjection, inClipFrustum, ioFlags,
+ group);
wasDataDirty = wasDataDirty || wasPathDirty;
}
} break;
@@ -1112,7 +1192,9 @@ namespace render {
IQt3DSRenderContext &theContext(m_Renderer.GetQt3DSContext());
return inLightProbe.ClearDirty(theContext.GetBufferManager(),
theContext.GetOffscreenRenderManager(),
- theContext.GetRenderPluginManager(), true);
+ theContext.GetRenderPluginManager(),
+ m_Layer.m_Scene->m_Presentation->m_preferKTX, true,
+ m_Layer.m_Scene->m_Presentation->m_flipCompressedTextures);
}
struct SLightNodeMarker
@@ -1161,12 +1243,187 @@ namespace render {
}
};
- void SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions)
+ void SLayerRenderPreparationData::calculateDynamicLayerSize(
+ SLayerRenderPreparationResult &prepResult)
+ {
+ m_boundPoints.clear();
+ if (m_Layer.m_DynamicCombine) {
+ // Combine all bounds of the layer objects to one spanning the whole active scene
+ // Only needs 8 projections but has low accuracy
+ NVBounds3 layerBounds;
+ layerBounds.setEmpty();
+ for (SNode *child = m_Layer.m_FirstChild; child; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()) {
+ auto &context = m_Renderer.GetQt3DSContext();
+ qt3ds::NVBounds3 childBounds = child->GetActiveBounds(
+ context.GetBufferManager(), context.GetPathManager());
+ if (childBounds.isEmpty() == false) {
+ childBounds.transform(child->m_GlobalTransform);
+ layerBounds.include(childBounds);
+ }
+ }
+ }
+
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.minimum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.minimum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.maximum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.maximum.y,
+ layerBounds.minimum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.minimum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.minimum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.maximum.x, layerBounds.maximum.y,
+ layerBounds.maximum.z);
+ m_boundPoints += QT3DSVec3(layerBounds.minimum.x, layerBounds.maximum.y,
+ layerBounds.maximum.z);
+ } else {
+ // Add 8 points for each active object to the point list
+ // Provides accurate 2d bounds, but causes a lot of projections for large scenes
+ for (SNode *child = m_Layer.m_FirstChild; child; child = child->m_NextSibling) {
+ if (child->m_Flags.IsActive()) {
+ auto &context = m_Renderer.GetQt3DSContext();
+ child->GetActiveBoundsList(m_boundPoints, context.GetBufferManager(),
+ context.GetPathManager(), child->m_GlobalTransform);
+ }
+ }
+ }
+
+ auto layerViewport = prepResult.GetLayerToPresentationViewport();
+
+ QT3DSVec2 projectedMinimum(std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::max());
+ QT3DSVec2 projectedMaximum(std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::lowest());
+
+ for (const auto &point : qAsConst(m_boundPoints)) {
+ QT3DSVec4 projectedPoint = m_ViewProjection.transform(QT3DSVec4(point, 1.0f));
+ projectedPoint.x /= projectedPoint.w;
+ projectedPoint.y /= projectedPoint.w;
+ projectedPoint.x += 1.0f;
+ projectedPoint.y += 1.0f;
+ projectedPoint.x *= 0.5f;
+ projectedPoint.y *= 0.5f;
+
+ QT3DSVec2 dims(QT3DSF32(layerViewport.m_Width),
+ QT3DSF32(layerViewport.m_Height));
+ projectedPoint.x *= dims.x;
+ projectedPoint.y *= dims.y;
+ projectedPoint.x += layerViewport.m_X;
+ projectedPoint.y += layerViewport.m_Y;
+
+ if (projectedPoint.x < projectedMinimum.x)
+ projectedMinimum.x = projectedPoint.x;
+ if (projectedPoint.y < projectedMinimum.y)
+ projectedMinimum.y = projectedPoint.y;
+ if (projectedPoint.x > projectedMaximum.x)
+ projectedMaximum.x = projectedPoint.x;
+ if (projectedPoint.y > projectedMaximum.y)
+ projectedMaximum.y = projectedPoint.y;
+ }
+
+ float boundsLeft = projectedMinimum.x;
+ float boundsBottom = projectedMinimum.y;
+ float boundsWidth = qAbs(projectedMaximum.x - projectedMinimum.x);
+ float boundsHeight = qAbs(projectedMaximum.y - projectedMinimum.y);
+
+ float paddedBoundsLeft = boundsLeft;
+ float paddedBoundsBottom = boundsBottom;
+ float paddedBoundsWidth = boundsWidth;
+ float paddedBoundsHeight = boundsHeight;
+
+ if (m_Layer.m_DynamicPadding > 0) {
+ float unpaddedBoundsLeft;
+ float unpaddedBoundsBottom;
+ float unpaddedBoundsWidth;
+ float unpaddedBoundsHeight;
+
+ if (m_Layer.m_DynamicPaddingUnits == LayerUnitTypes::Pixels) {
+ paddedBoundsLeft = boundsLeft - m_Layer.m_DynamicPadding;
+ paddedBoundsBottom = boundsBottom - m_Layer.m_DynamicPadding;
+ paddedBoundsWidth = boundsWidth + m_Layer.m_DynamicPadding * 2;
+ paddedBoundsHeight = boundsHeight + m_Layer.m_DynamicPadding * 2;
+
+ unpaddedBoundsLeft = boundsLeft + m_Layer.m_DynamicPadding;
+ unpaddedBoundsBottom = boundsBottom + m_Layer.m_DynamicPadding;
+ unpaddedBoundsWidth = boundsWidth - m_Layer.m_DynamicPadding * 2;
+ unpaddedBoundsHeight = boundsHeight - m_Layer.m_DynamicPadding * 2;
+ } else {
+ const float leftPadding = boundsWidth * m_Layer.m_DynamicPadding * 0.01f;
+ const float bottomPadding = boundsHeight * m_Layer.m_DynamicPadding * 0.01f;
+ const float widthPadding = m_Layer.m_DynamicPadding * 0.02f;
+ const float heightPadding = m_Layer.m_DynamicPadding * 0.02f;
+
+ paddedBoundsLeft = boundsLeft - leftPadding;
+ paddedBoundsBottom = boundsBottom - bottomPadding;
+ paddedBoundsWidth = boundsWidth * (1.0f + widthPadding);
+ paddedBoundsHeight = boundsHeight * (1.0f + heightPadding);
+
+ unpaddedBoundsLeft = boundsLeft + leftPadding;
+ unpaddedBoundsBottom = boundsBottom + bottomPadding;
+ unpaddedBoundsWidth = boundsWidth * (1.0f - widthPadding);
+ unpaddedBoundsHeight = boundsHeight * (1.0f - heightPadding);
+ }
+
+ // Both the padded and unpadded bounds are calculated
+ // Padded provides the upper bound when size has to be recalculated
+ // Unpadded provides the lower bound
+ // If the newly calculated bounds fit between the padded and unpadded ones
+ // use the previous calculations instead
+ if (m_Layer.m_DynamicPadding == m_lastDynamicPadding
+ && m_Layer.m_DynamicPaddingUnits == m_lastDynamicPaddingUnits
+ && m_unpaddedDynamicSize.m_X >= boundsLeft
+ && m_unpaddedDynamicSize.m_Y >= boundsBottom
+ && m_unpaddedDynamicSize.m_X + m_unpaddedDynamicSize.m_Width
+ <= boundsLeft + boundsWidth
+ && m_unpaddedDynamicSize.m_Y + m_unpaddedDynamicSize.m_Height
+ <= boundsBottom + boundsHeight
+ && m_dynamicSize.m_X <= boundsLeft
+ && m_dynamicSize.m_Y <= boundsBottom
+ && m_dynamicSize.m_X + m_dynamicSize.m_Width
+ >= boundsLeft + boundsWidth
+ && m_dynamicSize.m_Y + m_dynamicSize.m_Height
+ >= boundsBottom + boundsHeight) {
+ paddedBoundsLeft = m_dynamicSize.m_X;
+ paddedBoundsBottom = m_dynamicSize.m_Y;
+ paddedBoundsWidth = m_dynamicSize.m_Width;
+ paddedBoundsHeight = m_dynamicSize.m_Height;
+ } else {
+ m_unpaddedDynamicSize = NVRenderRectF(unpaddedBoundsLeft,
+ unpaddedBoundsBottom,
+ unpaddedBoundsWidth,
+ unpaddedBoundsHeight);
+ m_dynamicSize = NVRenderRectF(paddedBoundsLeft,
+ paddedBoundsBottom,
+ paddedBoundsWidth,
+ paddedBoundsHeight);
+ }
+ m_lastDynamicPadding = m_Layer.m_DynamicPadding;
+ m_lastDynamicPaddingUnits = m_Layer.m_DynamicPaddingUnits;
+ }
+
+ if (paddedBoundsLeft < layerViewport.m_X)
+ paddedBoundsLeft = layerViewport.m_X;
+ if (paddedBoundsBottom < layerViewport.m_Y)
+ paddedBoundsBottom = layerViewport.m_Y;
+ if (paddedBoundsWidth > layerViewport.m_Width)
+ paddedBoundsWidth = layerViewport.m_Width;
+ if (paddedBoundsHeight > layerViewport.m_Height)
+ paddedBoundsHeight = layerViewport.m_Height;
+
+ prepResult.setViewport(NVRenderRectF(paddedBoundsLeft, paddedBoundsBottom,
+ paddedBoundsWidth, paddedBoundsHeight));
+ }
+
+ bool SLayerRenderPreparationData::PrepareForRender(const QSize &inViewportDimensions)
{
QT3DS_PERF_SCOPED_TIMER(m_Renderer.GetQt3DSContext().GetPerfTimer(),
- "SLayerRenderData::PrepareForRender")
+ "LayerRenderData: PrepareForRender")
if (m_LayerPrepResult.hasValue())
- return;
+ return false;
m_Features.clear();
m_FeatureSetHash = 0;
@@ -1176,7 +1433,7 @@ namespace render {
NVRenderRect theViewport(theGraph.GetViewport());
NVRenderRect theScissor(theGraph.GetViewport());
if (theGraph.IsScissorTestEnabled())
- theScissor = m_Renderer.GetContext().GetScissorRect();
+ theScissor = theGraph.GetScissor();
bool wasDirty = false;
bool wasDataDirty = false;
wasDirty = m_Layer.m_Flags.IsDirty();
@@ -1189,10 +1446,10 @@ namespace render {
// Uncomment the line below to disable all progressive AA.
// maxNumAAPasses = 0;
- SLayerRenderPreparationResult thePrepResult;
bool hasOffscreenRenderer = GetOffscreenRenderer();
- bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f);
+ bool SSAOEnabled = (m_Layer.m_AoStrength > 0.0f && m_Layer.m_AoDistance > 0.0f
+ && m_Layer.m_AoEnabled);
bool SSDOEnabled = (m_Layer.m_ShadowStrength > 0.0f && m_Layer.m_ShadowDist > 0.0f);
SetShaderFeature("QT3DS_ENABLE_SSAO", SSAOEnabled);
SetShaderFeature("QT3DS_ENABLE_SSDO", SSDOEnabled);
@@ -1217,20 +1474,18 @@ namespace render {
&& theEffectSystem.DoesEffectRequireDepthTexture(theEffect->m_ClassName))
requiresDepthPrepass = true;
- if (theEffect->m_imageMaps && theEffect->m_imageMaps->size() > 0) {
+ if (theEffect->m_images.size() > 0) {
SRenderableImage *firstImage = nullptr;
SRenderableImage *nextImage = nullptr;
SShaderDefaultMaterialKey key;
SRenderableObjectFlags flags;
- auto iter = theEffect->m_imageMaps->begin();
- auto end = theEffect->m_imageMaps->end();
+ auto iter = theEffect->m_images.begin();
+ auto end = theEffect->m_images.end();
for (; iter != end; iter++) {
- if (iter->second) {
- PrepareImageForRender(*iter->second, ImageMapTypes::Unknown,
- firstImage, nextImage, flags, key,
- SShaderDefaultMaterialKeyProperties::ImageMapCount,
- nullptr);
- }
+ PrepareImageForRender(**iter, ImageMapTypes::Unknown,
+ firstImage, nextImage, flags, key,
+ SShaderDefaultMaterialKeyProperties::ImageMapCount,
+ nullptr);
}
}
}
@@ -1250,22 +1505,23 @@ namespace render {
maxNumAAPasses = 0;
}
- thePrepResult = SLayerRenderPreparationResult(SLayerRenderHelper(
+ m_LayerPrepResult = SLayerRenderPreparationResult(SLayerRenderHelper(
theViewport, theScissor, m_Layer.m_Scene->m_Presentation->m_PresentationDimensions,
m_Layer, shouldRenderToTexture, m_Renderer.GetQt3DSContext().GetScaleMode(),
m_Renderer.GetQt3DSContext().GetStereoMode(),
m_Renderer.GetQt3DSContext().GetStereoView(),
m_Renderer.GetQt3DSContext().GetStereoEyeSeparation(),
+ m_Renderer.GetQt3DSContext().GetStereoEyeRotation(),
m_Renderer.GetQt3DSContext().GetPresentationScaleFactor()));
- thePrepResult.m_LastEffect = theLastEffect;
- thePrepResult.m_MaxAAPassIndex = maxNumAAPasses;
- thePrepResult.m_Flags.SetRequiresDepthTexture(requiresDepthPrepass
+ m_LayerPrepResult->m_LastEffect = theLastEffect;
+ m_LayerPrepResult->m_MaxAAPassIndex = maxNumAAPasses;
+ m_LayerPrepResult->m_Flags.SetRequiresDepthTexture(requiresDepthPrepass
|| NeedsWidgetTexture());
- thePrepResult.m_Flags.SetShouldRenderToTexture(shouldRenderToTexture);
+ m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(shouldRenderToTexture);
if (m_Renderer.GetContext().GetRenderContextType() != NVRenderContextValues::GLES2)
- thePrepResult.m_Flags.SetRequiresSsaoPass(SSAOEnabled);
+ m_LayerPrepResult->m_Flags.SetRequiresSsaoPass(SSAOEnabled);
- if (thePrepResult.IsLayerVisible()) {
+ if (m_LayerPrepResult->IsLayerVisible()) {
if (shouldRenderToTexture) {
m_Renderer.GetQt3DSContext().GetRenderList().AddRenderTask(
CreateRenderToTextureRunnable());
@@ -1274,6 +1530,12 @@ namespace render {
m_Renderer.PrepareImageForIbl(*m_Layer.m_LightProbe);
wasDataDirty = true;
}
+ if (m_StereoMode != m_LayerPrepResult->getStereoMode()) {
+ // When stereo mode changes we need to mark data dirty
+ // for e.g. temporalAA to render correctly.
+ m_StereoMode = m_LayerPrepResult->getStereoMode();
+ wasDataDirty = true;
+ }
bool lightProbeValid = HasValidLightProbe(m_Layer.m_LightProbe);
@@ -1292,11 +1554,12 @@ namespace render {
// Push nodes in reverse depth first order
if (m_RenderableNodes.empty()) {
m_CamerasAndLights.clear();
+ m_GroupNodes.clear();
QT3DSU32 dfsIndex = 0;
for (SNode *theChild = m_Layer.m_FirstChild; theChild;
theChild = theChild->m_NextSibling)
- MaybeQueueNodeForRender(*theChild, m_RenderableNodes, m_CamerasAndLights,
- dfsIndex);
+ MaybeQueueNodeForRender(*theChild, m_RenderableNodes, m_GroupNodes,
+ m_CamerasAndLights, dfsIndex);
reverse(m_CamerasAndLights.begin(), m_CamerasAndLights.end());
reverse(m_RenderableNodes.begin(), m_RenderableNodes.end());
m_LightToNodeMap.clear();
@@ -1320,10 +1583,10 @@ namespace render {
// SetupCameraForRender() sets the camera used for picking and
// updates global state e.g. IsGloballyActive()
SCameraGlobalCalculationResult theResult =
- thePrepResult.SetupCameraForRender(*theCamera);
+ m_LayerPrepResult->SetupCameraForRender(*theCamera);
wasDataDirty = wasDataDirty || theResult.m_WasDirty;
if (theCamera->m_Flags.IsGloballyActive())
- m_Camera = thePrepResult.GetCamera();
+ m_Camera = m_LayerPrepResult->GetCamera();
if (theResult.m_ComputeFrustumSucceeded == false) {
qCCritical(INTERNAL_ERROR, "Failed to calculate camera frustum");
}
@@ -1363,7 +1626,7 @@ namespace render {
m_Lights.size() - 1, mapSize, mapSize,
NVRenderTextureFormats::R16F, 1, mapMode,
ShadowFilterValues::NONE);
- thePrepResult.m_Flags.SetRequiresShadowMapPass(true);
+ m_LayerPrepResult->m_Flags.SetRequiresShadowMapPass(true);
SetShaderFeature("QT3DS_ENABLE_SSM", true);
}
}
@@ -1430,9 +1693,13 @@ namespace render {
QT3DSF32 theTextScaleFactor = 1.0f;
if (m_Camera) {
m_Camera->CalculateViewProjectionMatrix(m_ViewProjection);
+
+ if (m_Layer.m_DynamicResize)
+ calculateDynamicLayerSize(*m_LayerPrepResult);
+
theTextScaleFactor = m_Camera->GetTextScaleFactor(
- thePrepResult.GetLayerToPresentationViewport(),
- thePrepResult.GetPresentationDesignDimensions());
+ m_LayerPrepResult->GetLayerToPresentationViewport(),
+ m_LayerPrepResult->GetPresentationDesignDimensions());
if (m_Camera->m_EnableFrustumCulling) {
SClipPlane nearPlane;
QT3DSMat33 theUpper33(m_Camera->m_GlobalTransform.getUpper3x3InverseTranspose());
@@ -1464,16 +1731,16 @@ namespace render {
bool renderablesDirty =
PrepareRenderablesForRender(m_ViewProjection,
m_ClippingFrustum,
- theTextScaleFactor, thePrepResult.m_Flags);
+ theTextScaleFactor, m_LayerPrepResult->m_Flags);
wasDataDirty = wasDataDirty || renderablesDirty;
- if (thePrepResult.m_Flags.RequiresStencilBuffer())
- thePrepResult.m_Flags.SetShouldRenderToTexture(true);
+ if (m_LayerPrepResult->m_Flags.RequiresStencilBuffer())
+ m_LayerPrepResult->m_Flags.SetShouldRenderToTexture(true);
} else {
NVRenderRect theViewport =
- thePrepResult.GetLayerToPresentationViewport().ToIntegerRect();
+ m_LayerPrepResult->GetLayerToPresentationViewport().ToIntegerRect();
bool theScissor = true;
NVRenderRect theScissorRect =
- thePrepResult.GetLayerToPresentationScissorRect().ToIntegerRect();
+ m_LayerPrepResult->GetLayerToPresentationScissorRect().ToIntegerRect();
// This happens here because if there are any fancy render steps
IRenderList &theRenderList(m_Renderer.GetQt3DSContext().GetRenderList());
NVRenderContext &theContext(m_Renderer.GetContext());
@@ -1503,12 +1770,13 @@ namespace render {
wasDataDirty = wasDataDirty || theResult.m_HasChangedSinceLastFrame;
}
}
+ } else {
+ // m_LayerPrepResult must always be set.
+ m_LayerPrepResult = SLayerRenderPreparationResult();
}
wasDirty = wasDirty || wasDataDirty;
- thePrepResult.m_Flags.SetWasDirty(wasDirty);
- thePrepResult.m_Flags.SetLayerDataDirty(wasDataDirty);
-
- m_LayerPrepResult = thePrepResult;
+ m_LayerPrepResult->m_Flags.SetWasDirty(wasDirty);
+ m_LayerPrepResult->m_Flags.SetLayerDataDirty(wasDataDirty);
// Per-frame cache of renderable objects post-sort.
GetOpaqueRenderableObjects();
@@ -1516,12 +1784,14 @@ namespace render {
GetTransparentRenderableObjects();
GetCameraDirection();
+ return wasDirty;
}
void SLayerRenderPreparationData::ResetForFrame()
{
m_TransparentObjects.clear_unsafe();
m_OpaqueObjects.clear_unsafe();
+ m_GroupObjects.clear_unsafe();
m_LayerPrepResult.setEmpty();
// The check for if the camera is or is not null is used
// to figure out if this layer was rendered at all.
diff --git a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
index eae29f6..fd9b86e 100644
--- a/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
+++ b/src/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.h
@@ -253,6 +253,7 @@ namespace render {
TNodeLightEntryPoolType m_RenderableNodeLightEntryPool;
nvvector<SRenderableNodeEntry> m_RenderableNodes;
+ nvvector<SRenderableNodeEntry> m_GroupNodes;
TLightToNodeMap m_LightToNodeMap; // map of lights to nodes to cache if we have looked up a
// given scoped light yet.
// Built at the same time as the renderable nodes map.
@@ -265,6 +266,12 @@ namespace render {
nvvector<SLight *> m_Lights; // Only contains lights that are global.
TRenderableObjectList m_OpaqueObjects;
TRenderableObjectList m_TransparentObjects;
+ TRenderableObjectList m_GroupObjects;
+ QVector<QT3DSVec3> m_boundPoints;
+ NVRenderRectF m_dynamicSize;
+ NVRenderRectF m_unpaddedDynamicSize;
+ float m_lastDynamicPadding = 0;
+ LayerUnitTypes::Enum m_lastDynamicPaddingUnits = LayerUnitTypes::Percent;
// Sorted lists of the rendered objects. There may be other transforms applied so
// it is simplest to duplicate the lists.
TRenderableObjectList m_RenderedOpaqueObjects;
@@ -294,6 +301,7 @@ namespace render {
bool m_FeaturesDirty;
size_t m_FeatureSetHash;
bool m_TooManyLightsError;
+ StereoModes::Enum m_StereoMode;
// shadow mapps
NVScopedRefCounted<Qt3DSShadowMap> m_ShadowMapManager;
@@ -323,23 +331,28 @@ namespace render {
bool PrepareModelForRender(SModel &inModel, const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,
- TNodeLightEntryList &inScopedLights);
+ TNodeLightEntryList &inScopedLights,
+ SOrderedGroupRenderable *group);
bool PrepareTextForRender(SText &inText, const QT3DSMat44 &inViewProjection,
QT3DSF32 inTextScaleFactor,
- SLayerRenderPreparationResultFlags &ioFlags);
+ SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group);
bool PreparePathForRender(SPath &inPath, const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,
- SLayerRenderPreparationResultFlags &ioFlags);
+ SLayerRenderPreparationResultFlags &ioFlags,
+ SOrderedGroupRenderable *group);
// Helper function used during PRepareForRender and PrepareAndRender
bool PrepareRenderablesForRender(const QT3DSMat44 &inViewProjection,
const Option<SClippingFrustum> &inClipFrustum,
QT3DSF32 inTextScaleFactor,
SLayerRenderPreparationResultFlags &ioFlags);
+ void calculateDynamicLayerSize(SLayerRenderPreparationResult &prepResult);
+
// returns true if this object will render something different than it rendered the last
// time.
- virtual void PrepareForRender(const QSize &inViewportDimensions);
+ virtual bool PrepareForRender(const QSize &inViewportDimensions);
bool CheckLightProbeDirty(SImage &inLightProbe);
void AddRenderWidget(IRenderWidget &inWidget);
void SetShaderFeature(const char *inName, bool inValue);
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
index 5c47a38..b93cb80 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
@@ -54,6 +54,222 @@
using namespace qt3ds::render;
+namespace qt3ds {
+namespace render {
+
+static const QString QT3DSTUDIO_TAG = QStringLiteral("qt3dstudio");
+
+static QFileInfo matchCaseInsensitiveFile(const QString& file)
+{
+ QStringList searchDirectories = QDir::searchPaths(QT3DSTUDIO_TAG);
+ std::reverse(searchDirectories.begin(), searchDirectories.end());
+
+ const auto searchFromPaths = [searchDirectories](QString file) -> QFileInfo {
+ QFileInfo fileInfo(file);
+ if (fileInfo.exists())
+ return fileInfo;
+
+ for (const auto &directoryPath : searchDirectories) {
+ auto path = QDir::cleanPath(directoryPath + '/' + file);
+ QFileInfo info(path);
+ if (info.exists())
+ return info;
+ }
+ return fileInfo;
+ };
+
+ QFileInfo info = searchFromPaths(file);
+ if (info.exists())
+ return info;
+
+ QString searchPath = file;
+
+ // Trying relative to search directories.
+ // First remove any ../ and ./ from the path
+ if (searchPath.startsWith(QLatin1String("../")))
+ searchPath = searchPath.right(searchPath.length() - 3);
+ else if (searchPath.startsWith(QLatin1String("./")))
+ searchPath = searchPath.right(searchPath.length() - 2);
+
+ int loops = 0;
+ while (++loops <= 4) {
+ info = searchFromPaths(searchPath);
+ if (info.exists())
+ return info;
+ searchPath.prepend(QLatin1String("../"));
+ }
+
+ return info;
+}
+
+static bool checkFileExists(const QString &tryFile, bool relative, QString &outFile)
+{
+ QFileInfo info;
+ if (relative)
+ info = matchCaseInsensitiveFile(tryFile);
+ else
+ info.setFile(tryFile);
+ if (info.exists()) {
+ outFile = info.filePath();
+ return true;
+ }
+ if (!relative) {
+ // Some textures, for example environment maps for custom materials,
+ // have absolute path at this point. It points to the wrong place with
+ // the new project structure, so we need to split it up and construct
+ // the new absolute path here.
+ QString wholePath = tryFile;
+ QStringList splitPath = wholePath.split(QLatin1String("../"));
+ if (splitPath.size() > 1) {
+ QString searchPath = splitPath.first() + splitPath.last();
+ int loops = 0;
+ while (++loops <= 3) {
+ info.setFile(searchPath);
+ if (info.exists()) {
+ outFile = info.filePath();
+ return true;
+ }
+ searchPath = splitPath.at(0);
+ for (int i = 0; i < loops; i++)
+ searchPath.append(QLatin1String("../"));
+ searchPath.append(splitPath.last());
+ }
+ }
+ }
+ return false;
+}
+
+// Locate existing file by adding a supported suffix to localFile.
+static bool existingImageFileForPath(const QString &localFile, bool relative, bool preferKTX,
+ QString &outPath)
+{
+ // Do nothing if given filepath exists without suffix
+ QFileInfo fi(localFile);
+ if (fi.exists()) {
+ outPath = localFile;
+ return true;
+ }
+
+ // Lists of supported image formats in preferred-first order.
+ const QStringList compressedFormats {"ktx", "astc", "dds"};
+ const QStringList nonCompressedFormats {"hdr", "png", "jpg", "jpeg", "gif"};
+
+ // Depending on preferKTX, check compressed formats before or after non-compressed ones.
+ QStringList supportedFormats = preferKTX ? compressedFormats + nonCompressedFormats
+ : nonCompressedFormats + compressedFormats;
+
+ // Check first if file exists from resources as that
+ // is common and optimal for integrity case.
+ for (const QString &suffix : supportedFormats) {
+ QString tryFile = ":/" + localFile + "." + suffix;
+ if (checkFileExists(tryFile, relative, outPath))
+ return true;
+ }
+ // If not found, check still file path as-is
+ for (const QString &suffix : supportedFormats) {
+ QString tryFile = localFile + "." + suffix;
+ if (checkFileExists(tryFile, relative, outPath))
+ return true;
+ }
+
+ outPath = localFile;
+ return false;
+}
+
+// Return resolved image path for unresolved source path.
+// Handle preferKtx, search paths, empty suffixes, schemas etc.
+QString IBufferManager::resolveImagePathInternal(const QString &sourcePath, bool preferKtx)
+{
+ QString path = sourcePath;
+ QUrl urlPath(path);
+
+ // Do nothing for image providers
+ if (urlPath.scheme() == QLatin1String("image"))
+ return sourcePath;
+
+ // Normalize the path
+ path = CFileTools::NormalizePathForQtUsage(path);
+ urlPath.setUrl(path);
+
+ const bool hasSuffix = urlPath.fileName().contains(QLatin1Char('.'));
+ const bool relative = urlPath.isRelative();
+
+ // Find an image file corresponding to only filename without suffix
+ if (!hasSuffix) {
+ QString outPath;
+ if (!existingImageFileForPath(path, relative, preferKtx, outPath))
+ return {};
+
+ return outPath;
+ }
+
+ // First check ktx files if preferKtx is set
+ QString result;
+ if (preferKtx) {
+ QString ktxSource = path;
+ const bool originalIsKtx = path.endsWith(QLatin1String("ktx"), Qt::CaseInsensitive);
+ if (!originalIsKtx) {
+ const int index = ktxSource.lastIndexOf(QLatin1Char('.'));
+ ktxSource = ktxSource.left(index);
+ ktxSource.append(QLatin1String(".ktx"));
+ }
+ if (checkFileExists(ktxSource, relative, result))
+ return result;
+ if (originalIsKtx)
+ return {};
+ }
+
+ if (checkFileExists(path, relative, result))
+ return result;
+
+ return {};
+}
+
+static QStringList s_failedPaths = {};
+
+QString IBufferManager::resolveImagePath(const QString &sourcePath, bool preferKtx)
+{
+ if (sourcePath.isEmpty())
+ return {};
+
+ if (!s_failedPaths.contains(sourcePath)) {
+ QString path = resolveImagePathInternal(sourcePath, preferKtx);
+ if (!path.isEmpty())
+ return path;
+
+ qCWarning(WARNING, "Failed to resolve path %s", qPrintable(sourcePath));
+ s_failedPaths.append(sourcePath);
+ }
+ return {};
+}
+
+QSet<QString> IBufferManager::resolveImageSet(const QSet<QString> &set, bool preferKtx)
+{
+ QSet<QString> ret;
+ for (auto &sourcePath : set) {
+ auto resolved = resolveImagePath(sourcePath, preferKtx);
+ if (!resolved.isEmpty())
+ ret.insert(resolved);
+ }
+ return ret;
+}
+
+QVector<CRegisteredString> IBufferManager::resolveSourcePaths(
+ IStringTable &strTable, const QVector<CRegisteredString> &sourcePaths, bool preferKtx)
+{
+ QVector<CRegisteredString> ret;
+ for (int i = 0; i < sourcePaths.size(); i++) {
+ QString path = QString::fromLatin1(sourcePaths[i].c_str());
+ auto resolved = strTable.RegisterStr(IBufferManager::resolveImagePath(path, preferKtx));
+ if (resolved.IsValid())
+ ret.append(resolved);
+ }
+ return ret;
+}
+
+}
+}
+
namespace {
using eastl::hash;
@@ -100,9 +316,9 @@ struct SBufferManager : public IBufferManager
typedef eastl::hash_set<CRegisteredString, eastl::hash<CRegisteredString>,
eastl::equal_to<CRegisteredString>, ForwardingAllocator>
TStringSet;
- typedef nvhash_map<CRegisteredString, SImageEntry> TImageMap;
+ typedef QHash<QString, SImageEntry> TImageMap;
typedef nvhash_map<CRegisteredString, SRenderMesh *> TMeshMap;
- typedef nvhash_map<CRegisteredString, CRegisteredString> TAliasImageMap;
+ typedef QMap<QString, QString> TAliasImageMap;
NVScopedRefCounted<NVRenderContext> m_Context;
NVScopedRefCounted<IStringTable> m_StrTable;
@@ -112,8 +328,8 @@ struct SBufferManager : public IBufferManager
TStr m_PathBuilder;
TImageMap m_ImageMap;
Mutex m_LoadedImageSetMutex;
- TStringSet m_LoadedImageSet;
- TAliasImageMap m_AliasImageMap;
+ QSet<QString> m_LoadedImageSet;
+ QMap<QString, QString> m_AliasImageMap;
TMeshMap m_MeshMap;
SPrimitiveEntry m_PrimitiveNames[5];
nvvector<qt3ds::render::NVRenderVertexBufferEntry> m_EntryBuffer;
@@ -122,6 +338,9 @@ struct SBufferManager : public IBufferManager
QHash<QString, QSharedPointer<QQmlImageProviderBase> > m_imageProviders;
QHash<QString, ReloadableTexturePtr> m_reloadableTextures;
+ ReloadableTexturePtr m_nullTexture;
+
+ bool m_allAstcPremultiplied = false;
static const char8_t *GetPrimitivesDirectory() { return "res//primitives"; }
@@ -133,131 +352,105 @@ struct SBufferManager : public IBufferManager
, m_PerfTimer(inTimer)
, mRefCount(0)
, m_PathBuilder(ForwardingAllocator(ctx.GetAllocator(), "SBufferManager::m_PathBuilder"))
- , m_ImageMap(ctx.GetAllocator(), "SBufferManager::m_ImageMap")
, m_LoadedImageSetMutex(ctx.GetAllocator())
- , m_LoadedImageSet(
- ForwardingAllocator(ctx.GetAllocator(), "SBufferManager::m_LoadedImageSet"))
- , m_AliasImageMap(ctx.GetAllocator(), "SBufferManager::m_AliasImageMap")
, m_MeshMap(ctx.GetAllocator(), "SBufferManager::m_MeshMap")
, m_EntryBuffer(ctx.GetAllocator(), "SBufferManager::m_EntryBuffer")
, m_GPUSupportsCompressedTextures(ctx.AreCompressedTexturesSupported())
, m_reloadableResources(false)
{
+#ifdef QT3DS_ALL_ASTC_PREMULTIPLIED
+ m_allAstcPremultiplied = true;
+#else
+ m_allAstcPremultiplied = qEnvironmentVariableIntValue("QT3DS_ALL_ASTC_PREMULTIPLIED");
+#endif
}
virtual ~SBufferManager() { Clear(); }
QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Context->GetAllocator())
- CRegisteredString CombineBaseAndRelative(const char8_t *inBase,
- const char8_t *inRelative) override
+ void checkAlwaysPremultiplied(const QString &resolvedPath,
+ SImageTextureFlags &textureFlags) override
{
- CFileTools::CombineBaseAndRelative(inBase, inRelative, m_PathBuilder);
- return m_StrTable->RegisterStr(m_PathBuilder.c_str());
+ if (m_allAstcPremultiplied) {
+ if (resolvedPath.endsWith(QStringLiteral(".astc")))
+ textureFlags.SetPreMultiplied(true);
+ }
}
- void SetImageHasTransparency(CRegisteredString inImagePath, bool inHasTransparency,
+ void SetImageHasTransparency(const QString &resolvedPath, bool inHasTransparency,
bool hasOpaque) override
{
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
- theImage.first->second.m_TextureFlags.SetHasTransparency(inHasTransparency);
- theImage.first->second.m_TextureFlags.setHasOpaquePixels(hasOpaque);
+ if (!m_ImageMap.contains(resolvedPath))
+ m_ImageMap.insert(resolvedPath, SImageEntry());
+ SImageEntry &entry = m_ImageMap[resolvedPath];
+ entry.m_TextureFlags.SetHasTransparency(inHasTransparency);
+ entry.m_TextureFlags.setHasOpaquePixels(hasOpaque);
+ checkAlwaysPremultiplied(resolvedPath, entry.m_TextureFlags);
}
- bool GetImageHasTransparency(CRegisteredString inSourcePath) const override
+ bool GetImageHasTransparency(const QString &resolvedPath) const override
{
- TImageMap::const_iterator theIter = m_ImageMap.find(inSourcePath);
+ TImageMap::const_iterator theIter = m_ImageMap.find(resolvedPath);
if (theIter != m_ImageMap.end())
- return theIter->second.m_TextureFlags.HasTransparency();
+ return theIter->m_TextureFlags.HasTransparency();
return false;
}
- bool GetImageHasOpaquePixels(CRegisteredString inSourcePath) const override
+ bool GetImageHasOpaquePixels(const QString &resolvedPath) const override
{
- TImageMap::const_iterator theIter = m_ImageMap.find(inSourcePath);
+ TImageMap::const_iterator theIter = m_ImageMap.find(resolvedPath);
if (theIter != m_ImageMap.end())
- return theIter->second.m_TextureFlags.HasOpaquePixels();
+ return theIter->m_TextureFlags.HasOpaquePixels();
return false;
}
- void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) override
+ void SetImageTransparencyToFalseIfNotSet(const QString &resolvedPath) override
{
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(inSourcePath, SImageEntry()));
- // If we did actually insert something
- if (theImage.second)
- theImage.first->second.m_TextureFlags.SetHasTransparency(false);
+ if (!m_ImageMap.contains(resolvedPath)) {
+ m_ImageMap.insert(resolvedPath, SImageEntry());
+ m_ImageMap[resolvedPath].m_TextureFlags.SetHasTransparency(false);
+ }
}
- void SetInvertImageUVCoords(CRegisteredString inImagePath, bool inShouldInvertCoords) override
+ void SetInvertImageUVCoords(const QString &resolvedPath, bool inShouldInvertCoords) override
{
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
- theImage.first->second.m_TextureFlags.SetInvertUVCoords(inShouldInvertCoords);
+ if (!m_ImageMap.contains(resolvedPath))
+ m_ImageMap.insert(resolvedPath, SImageEntry());
+ SImageEntry &entry = m_ImageMap[resolvedPath];
+ entry.m_TextureFlags.SetInvertUVCoords(inShouldInvertCoords);
}
- bool IsImageLoaded(CRegisteredString inSourcePath) override
+ bool IsImageLoaded(const QString &sourcePath) override
{
Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
- return m_LoadedImageSet.find(inSourcePath) != m_LoadedImageSet.end();
+ return m_LoadedImageSet.find(sourcePath) != m_LoadedImageSet.end();
}
- bool AliasImagePath(CRegisteredString inSourcePath, CRegisteredString inAliasPath,
- bool inIgnoreIfLoaded) override
+ bool AliasImagePath(const QString &resolvedPath, const QString &inAliasPath,
+ bool inIgnoreIfLoaded) override
{
- if (inSourcePath.IsValid() == false || inAliasPath.IsValid() == false)
+ if (resolvedPath.isEmpty() || inAliasPath.isEmpty())
return false;
// If the image is loaded then we ignore this call in some cases.
- if (inIgnoreIfLoaded && IsImageLoaded(inSourcePath))
+ if (inIgnoreIfLoaded && IsImageLoaded(resolvedPath))
return false;
- m_AliasImageMap.insert(eastl::make_pair(inSourcePath, inAliasPath));
+ m_AliasImageMap.insert(resolvedPath, inAliasPath);
return true;
}
- void UnaliasImagePath(CRegisteredString inSourcePath) override
+ void UnaliasImagePath(const QString &inSourcePath) override
{
- m_AliasImageMap.erase(inSourcePath);
+ m_AliasImageMap.remove(inSourcePath);
}
- CRegisteredString GetImagePath(CRegisteredString inSourcePath) override
+ QString GetImagePath(const QString &inSourcePath) override
{
TAliasImageMap::iterator theAliasIter = m_AliasImageMap.find(inSourcePath);
if (theAliasIter != m_AliasImageMap.end())
- return theAliasIter->second;
+ return *theAliasIter;
return inSourcePath;
}
- CRegisteredString getImagePath(const QString &path)
- {
- TAliasImageMap::iterator theAliasIter
- = m_AliasImageMap.find(m_StrTable->RegisterStr(qPrintable(path)));
- if (theAliasIter != m_AliasImageMap.end())
- return theAliasIter->second;
- return m_StrTable->RegisterStr(qPrintable(path));
- }
-
- static inline int wrapMod(int a, int base)
- {
- int ret = a % base;
- if (ret < 0)
- ret += base;
- return ret;
- }
-
- static inline void getWrappedCoords(int &sX, int &sY, int width, int height)
- {
- if (sY < 0) {
- sX -= width >> 1;
- sY = -sY;
- }
- if (sY >= height) {
- sX += width >> 1;
- sY = height - sY;
- }
- sX = wrapMod(sX, width);
- sY = wrapMod(sY, height);
- }
-
template <typename V, typename C>
void iterateAll(const V &vv, C c)
{
@@ -265,16 +458,16 @@ struct SBufferManager : public IBufferManager
c(x);
}
- void loadTextureImage(SReloadableImageTextureData &data)
+ void loadTextureImage(SReloadableImageTextureData &data, bool flipCompressed = false)
{
- CRegisteredString imagePath = getImagePath(data.m_path);
+ QString imagePath = GetImagePath(data.m_path);
TImageMap::iterator theIter = m_ImageMap.find(imagePath);
- if ((theIter == m_ImageMap.end() || theIter->second.m_Loaded == false)
- && imagePath.IsValid()) {
+ if ((theIter == m_ImageMap.end() || theIter->m_Loaded == false)
+ && !imagePath.isEmpty()) {
NVScopedReleasable<SLoadedTexture> theLoadedImage;
SImageTextureData textureData;
- doImageLoad(imagePath, theLoadedImage);
+ doImageLoad(imagePath, theLoadedImage, flipCompressed);
if (theLoadedImage) {
textureData = LoadRenderImage(imagePath, *theLoadedImage, data.m_scanTransparency,
@@ -287,14 +480,12 @@ struct SBufferManager : public IBufferManager
} else {
// We want to make sure that bad path fails once and doesn't fail over and over
// again which could slow down the system quite a bit.
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(imagePath, SImageEntry()));
- theImage.first->second.m_Loaded = true;
- qCWarning(WARNING, "Failed to load image: %s", imagePath.c_str());
- theIter = theImage.first;
+ auto theImage = m_ImageMap.insert(imagePath, SImageEntry());
+ theImage->m_Loaded = true;
+ qCWarning(WARNING) << "Failed to load image: " << imagePath;
}
} else {
- SImageEntry textureData = theIter->second;
+ const SImageEntry textureData = *theIter;
if (textureData.m_Loaded) {
data.m_Texture = textureData.m_Texture;
data.m_TextureFlags = textureData.m_TextureFlags;
@@ -316,36 +507,55 @@ struct SBufferManager : public IBufferManager
InvalidateBuffer(r);
}
- void loadSet(const QSet<QString> &imageSet) override
+ void loadSet(const QSet<QString> &imageSet, bool flipCompressed) override
{
- for (const auto &x : imageSet) {
- if (!m_reloadableTextures.contains(x)) {
- auto img = CreateReloadableImage(m_StrTable->RegisterStr(qPrintable(x)), false,
- false);
- img->m_initialized = false;
- loadTextureImage(*m_reloadableTextures[x]);
- } else if (!m_reloadableTextures[x]->m_loaded) {
- loadTextureImage(*m_reloadableTextures[x]);
+ for (const auto &sourcePath : imageSet) {
+ if (!m_reloadableTextures.contains(sourcePath)) {
+ auto img = CreateReloadableImage(sourcePath, false, false, flipCompressed);
+ if (img != m_nullTexture) {
+ img->m_initialized = false;
+ loadTextureImage(*m_reloadableTextures[sourcePath]);
+ }
+ } else if (!m_reloadableTextures[sourcePath]->m_loaded) {
+ loadTextureImage(*m_reloadableTextures[sourcePath]);
}
}
}
void unloadSet(const QSet<QString> &imageSet) override
{
- for (const auto &x : imageSet) {
- if (m_reloadableTextures.contains(x)) {
- if (m_reloadableTextures[x]->m_loaded)
- unloadTextureImage(*m_reloadableTextures[x]);
+ for (const auto &sourcePath : imageSet) {
+ if (m_reloadableTextures.contains(sourcePath)) {
+ if (m_reloadableTextures[sourcePath]->m_loaded)
+ unloadTextureImage(*m_reloadableTextures[sourcePath]);
}
}
}
- virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ void reloadAll(bool flipCompressed) override
+ {
+ for (const auto &tx : qAsConst(m_reloadableTextures)) {
+ if (tx->m_loaded) {
+ unloadTextureImage(*tx.data());
+ loadTextureImage(*tx.data(), flipCompressed);
+ }
+ }
+ }
+
+ virtual ReloadableTexturePtr CreateReloadableImage(const QString &inSourcePath,
bool inForceScanForTransparency,
- bool inBsdfMipmaps) override
+ bool inBsdfMipmaps,
+ bool flipCompressed) override
{
- QString path = QString::fromLatin1(inSourcePath.c_str());
+ const auto path = inSourcePath;
const bool inserted = m_reloadableTextures.contains(path);
+ if (path.isNull()) {
+ if (m_nullTexture.isNull()) {
+ m_nullTexture = ReloadableTexturePtr::create();
+ m_nullTexture->m_initialized = true;
+ }
+ return m_nullTexture;
+ }
if (!inserted || (inserted && m_reloadableTextures[path]->m_initialized == false)) {
if (!inserted)
m_reloadableTextures.insert(path, ReloadableTexturePtr::create());
@@ -354,15 +564,30 @@ struct SBufferManager : public IBufferManager
m_reloadableTextures[path]->m_bsdfMipmap = inBsdfMipmaps;
m_reloadableTextures[path]->m_initialized = true;
+
#ifndef LEGACY_ASTC_LOADING
if (!m_reloadableResources)
#endif
- loadTextureImage(*m_reloadableTextures[path]);
+ loadTextureImage(*m_reloadableTextures[path], flipCompressed);
- CRegisteredString imagePath = getImagePath(path);
+ QString imagePath = GetImagePath(path);
TImageMap::iterator theIter = m_ImageMap.find(imagePath);
+
+#ifndef NO_EXTERNAL_LOOKUP
+ // Failed to look up image from map, perhaps external of UIP/UIA image
+ // Try with full URI and load from filesystem.
+ if (theIter == m_ImageMap.end())
+ theIter = m_ImageMap.find(GetImagePath(inSourcePath));
+ if (theIter == m_ImageMap.end()) {
+ loadTextureImage(*m_reloadableTextures[path], flipCompressed);
+ imagePath = GetImagePath(path);
+ theIter = m_ImageMap.find(imagePath);
+ if (theIter == m_ImageMap.end())
+ theIter = m_ImageMap.find(GetImagePath(inSourcePath));
+ }
+#endif
if (theIter != m_ImageMap.end()) {
- SImageEntry textureData = theIter->second;
+ const SImageEntry textureData = *theIter;
if (textureData.m_Loaded) {
m_reloadableTextures[path]->m_Texture = textureData.m_Texture;
m_reloadableTextures[path]->m_TextureFlags = textureData.m_TextureFlags;
@@ -374,34 +599,50 @@ struct SBufferManager : public IBufferManager
return m_reloadableTextures[path];
}
- void doImageLoad(CRegisteredString inImagePath,
- NVScopedReleasable<SLoadedTexture> &theLoadedImage)
+ void doImageLoad(const QString inImagePath,
+ NVScopedReleasable<SLoadedTexture> &theLoadedImage,
+ bool inFlipCompressed = false)
{
- QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "Image Decompression")
+ QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "BufferManager: Image Decompression")
theLoadedImage = SLoadedTexture::Load(
- inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory,
- true, m_Context->GetRenderContextType(), false, this);
+ inImagePath, m_Context->GetFoundation(), *m_InputStreamFactory,
+ true, inFlipCompressed, m_Context->GetRenderContextType(), this);
// Hackish solution to custom materials not finding their textures if they are used
// in sub-presentations.
if (!theLoadedImage) {
- if (QDir(inImagePath.c_str()).isRelative()) {
- QString searchPath = inImagePath.c_str();
- if (searchPath.startsWith(QLatin1String("./")))
- searchPath.prepend(QLatin1Char('.'));
- int loops = 0;
- while (!theLoadedImage && ++loops <= 3) {
+ if (QDir(inImagePath).isRelative()) {
+ QString searchPath = inImagePath;
+
+ // Trying relative to search directories.
+ if (searchPath.startsWith(QLatin1String("../"))) {
+ auto searchPathRel = searchPath.right(searchPath.length() - 3);
theLoadedImage = SLoadedTexture::Load(
- searchPath.toUtf8(), m_Context->GetFoundation(),
- *m_InputStreamFactory, true,
- m_Context->GetRenderContextType(), false, this);
- searchPath.prepend(QLatin1String("../"));
+ searchPathRel.toUtf8(), m_Context->GetFoundation(),
+ *m_InputStreamFactory, true, false,
+ m_Context->GetRenderContextType(), this);
}
+
+ if (!theLoadedImage) {
+ if (searchPath.startsWith(QLatin1String("./")))
+ searchPath.prepend(QLatin1Char('.'));
+
+ int loops = 0;
+ while (!theLoadedImage && ++loops <= 3) {
+ theLoadedImage = SLoadedTexture::Load(
+ searchPath.toUtf8(), m_Context->GetFoundation(),
+ *m_InputStreamFactory, true, false,
+ m_Context->GetRenderContextType(), this);
+ searchPath.prepend(QLatin1String("../"));
+ }
+ }
+
+
} else {
// Some textures, for example environment maps for custom materials,
// have absolute path at this point. It points to the wrong place with
// the new project structure, so we need to split it up and construct
// the new absolute path here.
- QString wholePath = inImagePath.c_str();
+ QString wholePath = inImagePath;
QStringList splitPath = wholePath.split(QLatin1String("../"));
if (splitPath.size() > 1) {
QString searchPath = splitPath.at(0) + splitPath.at(1);
@@ -409,8 +650,8 @@ struct SBufferManager : public IBufferManager
while (!theLoadedImage && ++loops <= 3) {
theLoadedImage = SLoadedTexture::Load(
searchPath.toUtf8(), m_Context->GetFoundation(),
- *m_InputStreamFactory, true,
- m_Context->GetRenderContextType(), false, this);
+ *m_InputStreamFactory, true, false,
+ m_Context->GetRenderContextType(), this);
searchPath = splitPath.at(0);
for (int i = 0; i < loops; i++)
searchPath.append(QLatin1String("../"));
@@ -431,29 +672,35 @@ struct SBufferManager : public IBufferManager
return m_reloadableResources;
}
- SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ SImageTextureData LoadRenderImage(const QString &inImagePath,
SLoadedTexture &inLoadedImage,
bool inForceScanForTransparency, bool inBsdfMipmaps) override
{
- QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "Image Upload")
+ if (!QOpenGLContext::currentContext())
+ return SImageTextureData();
+ QT3DS_PERF_SCOPED_TIMER(m_PerfTimer, "BufferManager: Image Upload")
{
Mutex::ScopedLock __mapLocker(m_LoadedImageSetMutex);
m_LoadedImageSet.insert(inImagePath);
}
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
- bool wasInserted = theImage.second;
- theImage.first->second.m_Loaded = true;
+ bool wasInserted = !m_ImageMap.contains(inImagePath);
+ if (wasInserted)
+ m_ImageMap.insert(inImagePath, SImageEntry());
+
+ auto &theImage = m_ImageMap[inImagePath];
+ theImage.m_Loaded = true;
// inLoadedImage.EnsureMultiplerOfFour( m_Context->GetFoundation(), inImagePath.c_str() );
NVRenderTexture2D *theTexture = m_Context->CreateTexture2D();
if (inLoadedImage.data) {
qt3ds::render::NVRenderTextureFormats::Enum destFormat = inLoadedImage.format;
if (inBsdfMipmaps) {
- if (m_Context->GetRenderContextType() == render::NVRenderContextValues::GLES2)
- destFormat = qt3ds::render::NVRenderTextureFormats::RGBA8;
- else
- destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+ if (inLoadedImage.format != NVRenderTextureFormats::RGBE8) {
+ if (m_Context->GetRenderContextType() == render::NVRenderContextValues::GLES2)
+ destFormat = qt3ds::render::NVRenderTextureFormats::RGBA8;
+ else
+ destFormat = qt3ds::render::NVRenderTextureFormats::RGBA16F;
+ }
}
else {
theTexture->SetTextureData(
@@ -472,12 +719,12 @@ struct SBufferManager : public IBufferManager
if (inBsdfMipmaps
&& NVRenderTextureFormats::isUncompressedTextureFormat(inLoadedImage.format)) {
theTexture->SetMinFilter(NVRenderTextureMinifyingOp::LinearMipmapLinear);
- Qt3DSRenderPrefilterTexture *theBSDFMipMap = theImage.first->second.m_BSDFMipMap;
+ Qt3DSRenderPrefilterTexture *theBSDFMipMap = theImage.m_BSDFMipMap;
if (theBSDFMipMap == NULL) {
theBSDFMipMap = Qt3DSRenderPrefilterTexture::Create(
m_Context, inLoadedImage.width, inLoadedImage.height, *theTexture,
destFormat, m_Context->GetFoundation());
- theImage.first->second.m_BSDFMipMap = theBSDFMipMap;
+ theImage.m_BSDFMipMap = theBSDFMipMap;
}
if (theBSDFMipMap) {
@@ -486,7 +733,7 @@ struct SBufferManager : public IBufferManager
}
}
} else if (inLoadedImage.dds) {
- theImage.first->second.m_Texture = theTexture;
+ theImage.m_Texture = theTexture;
bool supportsCompressedTextures = m_GPUSupportsCompressedTextures;
bool isACompressedTexture
= NVRenderTextureFormats::isCompressedTextureFormat(inLoadedImage.format);
@@ -495,10 +742,10 @@ struct SBufferManager : public IBufferManager
// test code for DXT decompression
// if ( isDXT ) requiresDecompression = true;
if (requiresDecompression) {
- qCWarning(WARNING, PERF_INFO,
- "Image %s is compressed format which is unsupported by "
- "the graphics subsystem, decompressing in CPU",
- inImagePath.c_str());
+ qCWarning(WARNING, PERF_INFO)
+ << "Image %s is compressed format which is unsupported by "
+ << "the graphics subsystem, decompressing in CPU"
+ << inImagePath;
}
STextureData theDecompressedImage;
for (int idx = 0; idx < inLoadedImage.dds->numMipmaps; ++idx) {
@@ -528,25 +775,26 @@ struct SBufferManager : public IBufferManager
inLoadedImage.ReleaseDecompressedTexture(theDecompressedImage);
}
if (wasInserted || inForceScanForTransparency) {
- auto &flags = theImage.first->second.m_TextureFlags;
+ auto &flags = theImage.m_TextureFlags;
bool alsoOpaquePixels = false;
flags.SetHasTransparency(inLoadedImage.ScanForTransparency(alsoOpaquePixels));
flags.setHasOpaquePixels(alsoOpaquePixels);
+ checkAlwaysPremultiplied(inImagePath, flags);
}
- theImage.first->second.m_Texture = theTexture;
- return theImage.first->second;
+ theImage.m_Texture = theTexture;
+ return theImage;
}
- SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ SImageTextureData LoadRenderImage(const QString &inImagePath,
bool inForceScanForTransparency, bool inBsdfMipmaps) override
{
- inImagePath = GetImagePath(inImagePath);
+ const QString imagePath = GetImagePath(inImagePath);
- if (!inImagePath.IsValid())
+ if (imagePath.isEmpty())
return SImageEntry();
TImageMap::iterator theIter = m_ImageMap.find(inImagePath);
- if (theIter == m_ImageMap.end() && inImagePath.IsValid()) {
+ if (theIter == m_ImageMap.end() && !imagePath.isEmpty()) {
NVScopedReleasable<SLoadedTexture> theLoadedImage;
doImageLoad(inImagePath, theLoadedImage);
@@ -558,14 +806,13 @@ struct SBufferManager : public IBufferManager
// We want to make sure that bad path fails once and doesn't fail over and over
// again
// which could slow down the system quite a bit.
- pair<TImageMap::iterator, bool> theImage =
- m_ImageMap.insert(make_pair(inImagePath, SImageEntry()));
- theImage.first->second.m_Loaded = true;
- qCWarning(WARNING, "Failed to load image: %s", inImagePath.c_str());
- theIter = theImage.first;
+ auto theImage = m_ImageMap.insert(inImagePath, SImageEntry());
+ theImage->m_Loaded = true;
+ qCWarning(WARNING) << "Failed to load image: " << inImagePath;
+ theIter = theImage;
}
}
- return theIter->second;
+ return *theIter;
}
qt3dsimp::SMultiLoadResult LoadPrimitive(const char8_t *inRelativePath)
@@ -868,6 +1115,8 @@ struct SBufferManager : public IBufferManager
SRenderMesh *LoadMesh(CRegisteredString inMeshPath) override
{
+ if (!QOpenGLContext::currentContext())
+ return nullptr;
if (inMeshPath.IsValid() == false)
return nullptr;
pair<TMeshMap::iterator, bool> theMesh =
@@ -1077,7 +1326,7 @@ struct SBufferManager : public IBufferManager
m_MeshMap.clear();
for (TImageMap::iterator iter = m_ImageMap.begin(), end = m_ImageMap.end(); iter != end;
++iter) {
- SImageEntry &theEntry = iter->second;
+ SImageEntry &theEntry = *iter;
ReleaseTexture(theEntry);
}
m_ImageMap.clear();
@@ -1100,14 +1349,15 @@ struct SBufferManager : public IBufferManager
}
}
{
- TImageMap::iterator iter = m_ImageMap.find(inSourcePath);
+ const QString imagePath = QString::fromLatin1(inSourcePath.c_str());
+ TImageMap::iterator iter = m_ImageMap.find(imagePath);
if (iter != m_ImageMap.end()) {
- SImageEntry &theEntry = iter->second;
+ SImageEntry &theEntry = *iter;
ReleaseTexture(theEntry);
- m_ImageMap.erase(inSourcePath);
+ m_ImageMap.remove(imagePath);
{
Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
- m_LoadedImageSet.erase(inSourcePath);
+ m_LoadedImageSet.remove(imagePath);
}
}
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
index b8cd49b..a0f4606 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
@@ -54,20 +54,17 @@ namespace render {
virtual ~IBufferManager() {}
public:
- // Path manipulation used to get the final path form a base path plus relative extension
- virtual CRegisteredString CombineBaseAndRelative(const char8_t *inBase,
- const char8_t *inRelative) = 0;
- virtual void SetImageHasTransparency(CRegisteredString inSourcePath,
+ virtual void SetImageHasTransparency(const QString &resolvedPath,
bool inHasTransparency, bool alsoOpaque) = 0;
- virtual bool GetImageHasTransparency(CRegisteredString inSourcePath) const = 0;
- virtual bool GetImageHasOpaquePixels(CRegisteredString inSourcePath) const = 0;
- virtual void SetImageTransparencyToFalseIfNotSet(CRegisteredString inSourcePath) = 0;
- virtual void SetInvertImageUVCoords(CRegisteredString inSourcePath,
+ virtual bool GetImageHasTransparency(const QString &resolvedPath) const = 0;
+ virtual bool GetImageHasOpaquePixels(const QString &resolvedPath) const = 0;
+ virtual void SetImageTransparencyToFalseIfNotSet(const QString &resolvedPathh) = 0;
+ virtual void SetInvertImageUVCoords(const QString &resolvedPath,
bool inShouldInvertCoords) = 0;
// Returns true if this image has been loaded into memory
// This call is threadsafe. Nothing else on this object is guaranteed to be.
- virtual bool IsImageLoaded(CRegisteredString inSourcePath) = 0;
+ virtual bool IsImageLoaded(const QString &sourcePath) = 0;
// Alias one image path with another image path. Optionally this object will ignore the
// call if
@@ -75,32 +72,40 @@ namespace render {
// to be shown
// in place of an image that is loading offline.
// Returns true if the image was aliased, false otherwise.
- virtual bool AliasImagePath(CRegisteredString inSourcePath, CRegisteredString inAliasPath,
+ virtual bool AliasImagePath(const QString &resolvedPath, const QString &inAliasPath,
bool inIgnoreIfLoaded) = 0;
- virtual void UnaliasImagePath(CRegisteredString inSourcePath) = 0;
+ virtual void UnaliasImagePath(const QString &resolvedPath) = 0;
+
+ // Return resolved imagepaths from unresolved sourcepaths
+ static QString resolveImagePath(const QString &sourcePath, bool preferKtx);
+ static QSet<QString> resolveImageSet(const QSet<QString> &set, bool preferKtx);
+ static QVector<CRegisteredString> resolveSourcePaths(IStringTable &strTable,
+ const QVector<CRegisteredString> &sourcePaths, bool preferKtx);
// Returns the given source path unless the source path is aliased; in which case returns
// the aliased path.
- virtual CRegisteredString GetImagePath(CRegisteredString inSourcePath) = 0;
+ virtual QString GetImagePath(const QString &sourcePath) = 0;
// Returns a texture and a boolean indicating if this texture has transparency in it or not.
// Can't name this LoadImage because that gets mangled by windows to LoadImageA (uggh)
// In some cases we need to only scan particular images for transparency.
- virtual SImageTextureData LoadRenderImage(CRegisteredString inImagePath,
+ virtual SImageTextureData LoadRenderImage(const QString &sourcePath,
SLoadedTexture &inTexture,
bool inForceScanForTransparency = false,
bool inBsdfMipmaps = false) = 0;
- virtual SImageTextureData LoadRenderImage(CRegisteredString inSourcePath,
+ virtual SImageTextureData LoadRenderImage(const QString &sourcePath,
bool inForceScanForTransparency = false,
bool inBsdfMipmaps = false) = 0;
- virtual ReloadableTexturePtr CreateReloadableImage(CRegisteredString inSourcePath,
+ virtual ReloadableTexturePtr CreateReloadableImage(const QString &inSourcePath,
bool inForceScanForTransparency = false,
- bool inBsdfMipmaps = false) = 0;
+ bool inBsdfMipmaps = false,
+ bool flipCompressed = false) = 0;
virtual void enableReloadableResources(bool enable) = 0;
virtual bool isReloadableResourcesEnabled() const = 0;
- virtual void loadSet(const QSet<QString> &imageSet) = 0;
- virtual void unloadSet(const QSet<QString> &imageSet) = 0;
+ virtual void loadSet(const QSet<QString> &resolvedImageSet, bool flipCompressed) = 0;
+ virtual void unloadSet(const QSet<QString> &resolvedImageSet) = 0;
+ virtual void reloadAll(bool flipCompressed) = 0;
virtual void loadCustomMesh(const QString &name, qt3dsimp::Mesh *mesh) = 0;
virtual SRenderMesh *LoadMesh(CRegisteredString inSourcePath) = 0;
@@ -118,9 +123,14 @@ namespace render {
virtual void InvalidateBuffer(CRegisteredString inSourcePath) = 0;
virtual IStringTable &GetStringTable() = 0;
+ virtual void checkAlwaysPremultiplied(const QString &resolvedPath,
+ SImageTextureFlags &textureFlags) = 0;
+
static IBufferManager &Create(NVRenderContext &inRenderContext, IStringTable &inStrTable,
IInputStreamFactory &inInputStreamFactory,
IPerfTimer &inTimer);
+ private:
+ static QString resolveImagePathInternal(const QString &sourcePath, bool preferKtx);
};
}
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
index 37f965b..253f481 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
@@ -54,12 +54,12 @@ typedef Mutex::ScopedLock TScopedLock;
struct SLoadingImage
{
SImageLoaderBatch *m_Batch;
- CRegisteredString m_SourcePath;
+ QString m_SourcePath;
QT3DSU64 m_TaskId;
SLoadingImage *m_Tail;
// Called from main thread
- SLoadingImage(CRegisteredString inSourcePath)
+ SLoadingImage(const QString &inSourcePath)
: m_Batch(NULL)
, m_SourcePath(inSourcePath)
, m_TaskId(0)
@@ -108,22 +108,23 @@ struct SImageLoaderBatch
QT3DSU32 m_FinalizedImageCount;
QT3DSU32 m_NumImages;
NVRenderContextType m_contextType;
- bool m_preferKTX;
+ bool m_flipCompressedTextures;
bool m_ibl;
// Called from main thread
static SImageLoaderBatch *CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBatchId,
- NVConstDataRef<CRegisteredString> inSourcePaths,
- CRegisteredString inImageTillLoaded,
+ const QVector<QString> &inSourcePaths,
+ const QString &inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType contextType,
- bool preferKTX, bool ibl);
+ bool iblImage,
+ bool flipCompressedTextures);
// Called from main thread
SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
const TLoadingImageList &inImageList, TImageBatchId inBatchId,
- QT3DSU32 inImageCount, NVRenderContextType contextType,
- bool preferKTX, bool ibl);
+ QT3DSU32 inImageCount, NVRenderContextType contextType, bool ibl,
+ bool flipCompressedTextures);
// Called from main thread
~SImageLoaderBatch();
@@ -153,12 +154,12 @@ struct SImageLoaderBatch
}
// Called from main thread
void Cancel();
- void Cancel(CRegisteredString inSourcePath);
+ void Cancel(const QString &inSourcePath);
};
struct SBatchLoadedImage
{
- CRegisteredString m_SourcePath;
+ QString m_SourcePath;
SLoadedTexture *m_Texture;
SImageLoaderBatch *m_Batch;
SBatchLoadedImage()
@@ -168,7 +169,7 @@ struct SBatchLoadedImage
}
// Called from loading thread
- SBatchLoadedImage(CRegisteredString inSourcePath, SLoadedTexture *inTexture,
+ SBatchLoadedImage(QString inSourcePath, SLoadedTexture *inTexture,
SImageLoaderBatch &inBatch)
: m_SourcePath(inSourcePath)
, m_Texture(inTexture)
@@ -183,7 +184,7 @@ struct SBatchLoadedImage
struct SBatchLoader : public IImageBatchLoader
{
typedef nvhash_map<TImageBatchId, SImageLoaderBatch *> TImageLoaderBatchMap;
- typedef nvhash_map<CRegisteredString, TImageBatchId> TSourcePathToBatchMap;
+ typedef QMap<QString, TImageBatchId> TSourcePathToBatchMap;
typedef Pool<SLoadingImage, ForwardingAllocator> TLoadingImagePool;
typedef Pool<SImageLoaderBatch, ForwardingAllocator> TBatchPool;
@@ -229,7 +230,6 @@ struct SBatchLoader : public IImageBatchLoader
, m_LoaderMutex(inFoundation.getAllocator())
, m_LoadedImages(inFoundation.getAllocator(), "SBatchLoader::m_LoadedImages")
, m_FinishedBatches(inFoundation.getAllocator(), "SBatchLoader::m_FinishedBatches")
- , m_SourcePathToBatches(inFoundation.getAllocator(), "SBatchLoader::m_SourcePathToBatches")
, m_LoaderBuilderWorkspace(inFoundation.getAllocator(),
"SBatchLoader::m_LoaderBuilderWorkspace")
, m_LoadingImagePool(
@@ -259,11 +259,12 @@ struct SBatchLoader : public IImageBatchLoader
// paths
// until said path is loaded.
// An optional listener can be passed in to get callbacks about the batch.
- TImageBatchId LoadImageBatch(NVConstDataRef<CRegisteredString> inSourcePaths,
- CRegisteredString inImageTillLoaded,
+ TImageBatchId LoadImageBatch(const QVector<QString> &inSourcePaths,
+ const QString &inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType contextType,
- bool preferKTX, bool iblImages) override
+ bool iblImages,
+ bool flipCompressedTextures) override
{
if (inSourcePaths.size() == 0)
return 0;
@@ -279,7 +280,7 @@ struct SBatchLoader : public IImageBatchLoader
SImageLoaderBatch *theBatch(SImageLoaderBatch::CreateLoaderBatch(
*this, theBatchId, inSourcePaths, inImageTillLoaded, inListener, contextType,
- preferKTX, iblImages));
+ iblImages, flipCompressedTextures));
if (theBatch) {
m_Batches.insert(eastl::make_pair(theBatchId, theBatch));
return theBatchId;
@@ -295,12 +296,12 @@ struct SBatchLoader : public IImageBatchLoader
}
// Blocks if the image is currently in-flight
- void CancelImageLoading(CRegisteredString inSourcePath) override
+ void CancelImageLoading(const QString &inSourcePath) override
{
TScopedLock __loaderLock(m_LoaderMutex);
TSourcePathToBatchMap::iterator theIter = m_SourcePathToBatches.find(inSourcePath);
if (theIter != m_SourcePathToBatches.end()) {
- TImageBatchId theBatchId = theIter->second;
+ const TImageBatchId &theBatchId = theIter.value();
TImageLoaderBatchMap::iterator theBatchIter = m_Batches.find(theBatchId);
if (theBatchIter != m_Batches.end())
theBatchIter->second->Cancel(inSourcePath);
@@ -331,6 +332,8 @@ struct SBatchLoader : public IImageBatchLoader
void ImageLoaded(SLoadingImage &inImage, SLoadedTexture *inTexture)
{
TScopedLock __loaderLock(m_LoaderMutex);
+ if (inTexture == nullptr)
+ qCWarning(WARNING) << "Failed to load image: " << inImage.m_SourcePath;
m_LoadedImages.push_back(
SBatchLoadedImage(inImage.m_SourcePath, inTexture, *inImage.m_Batch));
inImage.m_Batch->IncrementLoadedImageCount();
@@ -343,7 +346,7 @@ struct SBatchLoader : public IImageBatchLoader
// Pass 1 - send out all image loaded signals
for (QT3DSU32 idx = 0, end = m_LoadedImages.size(); idx < end; ++idx) {
- m_SourcePathToBatches.erase(m_LoadedImages[idx].m_SourcePath);
+ m_SourcePathToBatches.remove(m_LoadedImages[idx].m_SourcePath);
m_LoadedImages[idx].Finalize(m_BufferManager);
m_LoadedImages[idx].m_Batch->IncrementFinalizedImageCount();
if (m_LoadedImages[idx].m_Batch->IsFinalizedFinished())
@@ -382,13 +385,13 @@ void SLoadingImage::Setup(SImageLoaderBatch &inBatch)
void SLoadingImage::LoadImage(void *inImg)
{
SLoadingImage *theThis = reinterpret_cast<SLoadingImage *>(inImg);
- QT3DS_PERF_SCOPED_TIMER(theThis->m_Batch->m_Loader.m_PerfTimer, "Image Decompression")
+ QT3DS_PERF_SCOPED_TIMER(theThis->m_Batch->m_Loader.m_PerfTimer, "BatchLoader: Image Decompression")
if (theThis->m_Batch->m_Loader.m_BufferManager.IsImageLoaded(theThis->m_SourcePath) == false) {
SLoadedTexture *theTexture = SLoadedTexture::Load(
- theThis->m_SourcePath.c_str(), theThis->m_Batch->m_Loader.m_Foundation,
+ theThis->m_SourcePath, theThis->m_Batch->m_Loader.m_Foundation,
theThis->m_Batch->m_Loader.m_InputStreamFactory, true,
+ theThis->m_Batch->m_flipCompressedTextures,
theThis->m_Batch->m_contextType,
- theThis->m_Batch->m_preferKTX,
&theThis->m_Batch->m_Loader.m_BufferManager);
// if ( theTexture )
// theTexture->EnsureMultiplerOfFour( theThis->m_Batch->m_Loader.m_Foundation,
@@ -409,7 +412,6 @@ void SLoadingImage::TaskCancelled(void *inImg)
bool SBatchLoadedImage::Finalize(IBufferManager &inMgr)
{
if (m_Texture) {
- eastl::string thepath(m_SourcePath);
bool isIBL = this->m_Batch->m_ibl;
inMgr.LoadRenderImage(m_SourcePath, *m_Texture, false, isIBL);
inMgr.UnaliasImagePath(m_SourcePath);
@@ -428,31 +430,29 @@ bool SBatchLoadedImage::Finalize(IBufferManager &inMgr)
SImageLoaderBatch *
SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBatchId,
- NVConstDataRef<CRegisteredString> inSourcePaths,
- CRegisteredString inImageTillLoaded,
+ const QVector<QString> &inSourcePaths,
+ const QString &inImageTillLoaded,
IImageLoadListener *inListener,
- NVRenderContextType contextType,
- bool preferKTX, bool iblImages)
+ NVRenderContextType contextType, bool iblImages,
+ bool flipCompressedTextures)
{
TLoadingImageList theImages;
QT3DSU32 theLoadingImageCount = 0;
for (QT3DSU32 idx = 0, end = inSourcePaths.size(); idx < end; ++idx) {
- CRegisteredString theSourcePath(inSourcePaths[idx]);
+ const QString theSourcePath(inSourcePaths[idx]);
- if (theSourcePath.IsValid() == false)
+ if (theSourcePath.isEmpty())
continue;
if (inLoader.m_BufferManager.IsImageLoaded(theSourcePath))
continue;
- eastl::pair<SBatchLoader::TSourcePathToBatchMap::iterator, bool> theInserter =
- inLoader.m_SourcePathToBatches.insert(eastl::make_pair(inSourcePaths[idx], inBatchId));
-
- // If the loader has already seen this image.
- if (theInserter.second == false)
+ if (inLoader.m_SourcePathToBatches.contains(inSourcePaths[idx]))
continue;
- if (inImageTillLoaded.IsValid()) {
+ inLoader.m_SourcePathToBatches.insert(inSourcePaths[idx], inBatchId);
+
+ if (!inImageTillLoaded.isEmpty()) {
// Alias the image so any further requests for this source path will result in
// the default images (image till loaded).
bool aliasSuccess =
@@ -470,7 +470,7 @@ SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBat
(SImageLoaderBatch *)inLoader.m_BatchPool.allocate(__FILE__, __LINE__);
new (theBatch)
SImageLoaderBatch(inLoader, inListener, theImages, inBatchId, theLoadingImageCount,
- contextType, preferKTX, iblImages);
+ contextType, iblImages, flipCompressedTextures);
return theBatch;
}
return NULL;
@@ -479,7 +479,7 @@ SImageLoaderBatch::CreateLoaderBatch(SBatchLoader &inLoader, TImageBatchId inBat
SImageLoaderBatch::SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener *inLoadListener,
const TLoadingImageList &inImageList, TImageBatchId inBatchId,
QT3DSU32 inImageCount, NVRenderContextType contextType,
- bool preferKTX, bool ibl)
+ bool ibl, bool flipCompressedTextures)
: m_Loader(inLoader)
, m_LoadListener(inLoadListener)
, m_LoadEvent(inLoader.m_Foundation.getAllocator())
@@ -490,8 +490,8 @@ SImageLoaderBatch::SImageLoaderBatch(SBatchLoader &inLoader, IImageLoadListener
, m_FinalizedImageCount(0)
, m_NumImages(inImageCount)
, m_contextType(contextType)
- , m_preferKTX(preferKTX)
, m_ibl(ibl)
+ , m_flipCompressedTextures(flipCompressedTextures)
{
for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
++iter) {
@@ -516,7 +516,7 @@ void SImageLoaderBatch::Cancel()
m_Loader.m_ThreadPool.CancelTask(iter->m_TaskId);
}
-void SImageLoaderBatch::Cancel(CRegisteredString inSourcePath)
+void SImageLoaderBatch::Cancel(const QString &inSourcePath)
{
for (TLoadingImageList::iterator iter = m_Images.begin(), end = m_Images.end(); iter != end;
++iter) {
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
index 2805940..e8fd82d 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.h
@@ -51,7 +51,7 @@ namespace render {
virtual ~IImageLoadListener() {}
public:
- virtual void OnImageLoadComplete(CRegisteredString inPath,
+ virtual void OnImageLoadComplete(const QString &inPath,
ImageLoadResult::Enum inResult) = 0;
virtual void OnImageBatchComplete(QT3DSU64 inBatch) = 0;
};
@@ -69,15 +69,16 @@ namespace render {
// source paths
// until said path is loaded.
// An optional listener can be passed in to get callbacks about the batch.
- virtual TImageBatchId LoadImageBatch(NVConstDataRef<CRegisteredString> inSourcePaths,
- CRegisteredString inImageTillLoaded,
+ virtual TImageBatchId LoadImageBatch(const QVector<QString> &inSourcePaths,
+ const QString &inImageTillLoaded,
IImageLoadListener *inListener,
NVRenderContextType type,
- bool preferKTX, bool iblImages) = 0;
+ bool iblImages,
+ bool flipCompressedTextures = false) = 0;
// Blocks if any of the images in the batch are in flight
virtual void CancelImageBatchLoading(TImageBatchId inBatchId) = 0;
// Blocks if the image is currently in-flight
- virtual void CancelImageLoading(CRegisteredString inSourcePath) = 0;
+ virtual void CancelImageLoading(const QString &inSourcePath) = 0;
// Block until every image in the batch is loaded.
virtual void BlockUntilLoaded(TImageBatchId inId) = 0;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
index 577bd55..14816e4 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
@@ -41,6 +41,7 @@
#include <QtQuick/qquickimageprovider.h>
#include <QtGui/qimage.h>
#include <QtGui/qopengltexture.h>
+#include <QtCore/qfileinfo.h>
#include <private/qnumeric_p.h>
@@ -680,8 +681,9 @@ bool ScanImageForAlpha(const void *inData, QT3DSU32 inWidth, QT3DSU32 inHeight,
QT3DSU32 alphaRightShift = inPixelSizeInBytes * 8 - inAlphaSizeInBits;
QT3DSU32 maxAlphaValue = (1 << inAlphaSizeInBits) - 1;
- for (QT3DSU32 rowIdx = 0; rowIdx < inHeight && hasAlpha == false; ++rowIdx) {
- for (QT3DSU32 idx = 0; idx < inWidth && hasAlpha == false;
+ for (QT3DSU32 rowIdx = 0; rowIdx < inHeight && (hasAlpha == false || hasOpaque == false);
+ ++rowIdx) {
+ for (QT3DSU32 idx = 0; idx < inWidth && (hasAlpha == false || hasOpaque == false);
++idx, rowPtr += inPixelSizeInBytes) {
QT3DSU32 pixelValue = 0;
if (inPixelSizeInBytes == 2)
@@ -738,6 +740,7 @@ bool SLoadedTexture::ScanForTransparency(bool &alsoOpaquePixels)
// Scan the image.
case NVRenderTextureFormats::SRGB8:
case NVRenderTextureFormats::RGB8:
+ case NVRenderTextureFormats::RGBE8:
return false;
break;
case NVRenderTextureFormats::RGB565:
@@ -818,6 +821,7 @@ bool SLoadedTexture::ScanForTransparency(bool &alsoOpaquePixels)
case NVRenderTextureFormats::SRGB8_Alpha8_ASTC_10x10:
case NVRenderTextureFormats::SRGB8_Alpha8_ASTC_12x10:
case NVRenderTextureFormats::SRGB8_Alpha8_ASTC_12x12:
+ case NVRenderTextureFormats::RGBA8_ETC2_EAC:
return false;
default:
break;
@@ -905,44 +909,26 @@ void SLoadedTexture::ReleaseDecompressedTexture(STextureData inImage)
m_Allocator.deallocate(inImage.data);
}
-#ifndef EA_PLATFORM_WINDOWS
-#define stricmp strcasecmp
-#endif
-
-SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &inFoundation,
+SLoadedTexture *SLoadedTexture::Load(const QString &path, NVFoundationBase &inFoundation,
IInputStreamFactory &inFactory, bool inFlipY,
- NVRenderContextType renderContextType, bool preferKTX,
+ bool inFlipCompressed,
+ NVRenderContextType renderContextType,
IBufferManager *bufferManager)
{
- if (inPath.isEmpty())
+ if (path.isEmpty())
return nullptr;
- if (QUrl(inPath).scheme() == QLatin1String("image"))
- return LoadQImage(inPath, inFlipY, inFoundation, renderContextType, bufferManager);
-
- // Check KTX path first
- QString path = inPath;
- QString ktxSource = inPath;
- if (preferKTX) {
- ktxSource = ktxSource.left(ktxSource.lastIndexOf(QLatin1Char('.')));
- ktxSource.append(QLatin1String(".ktx"));
- }
+ if (QUrl(path).scheme() == QLatin1String("image"))
+ return LoadQImage(path, inFlipY, inFoundation, renderContextType, bufferManager);
SLoadedTexture *theLoadedImage = nullptr;
- // We will get invalid error logs of files not found if we don't force quiet mode
- // If the file is actually missing, it will be logged later (loaded image is null)
- NVScopedRefCounted<IRefCountedInputStream> theStream(
- inFactory.GetStreamForFile(preferKTX ? ktxSource : inPath, true));
- if (!theStream.mPtr) {
- if (preferKTX)
- theStream = inFactory.GetStreamForFile(inPath, true);
- else
- return nullptr;
- } else {
- path = ktxSource;
- }
+ NVScopedRefCounted<IRefCountedInputStream> theStream(inFactory.GetStreamForFile(path, true));
+
+ if (!theStream.mPtr)
+ return nullptr;
+
QString fileName;
- inFactory.GetPathForFile(path, fileName, true);
+ inFactory.GetPathForStream(theStream.mPtr, fileName);
if (theStream.mPtr && path.size() > 3) {
if (path.endsWith(QLatin1String("png"), Qt::CaseInsensitive)
|| path.endsWith(QLatin1String("jpg"), Qt::CaseInsensitive)
@@ -957,11 +943,17 @@ SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &in
} else if (path.endsWith(QLatin1String("hdr"), Qt::CaseInsensitive)) {
theLoadedImage = LoadHDR(*theStream, inFoundation, renderContextType);
} else if (path.endsWith(QLatin1String("ktx"), Qt::CaseInsensitive)) {
+ // We need to flip y coordinate in shader as it cannot be done at load time for
+ // compressed textures.
+ bufferManager->SetInvertImageUVCoords(path, inFlipCompressed);
theLoadedImage = LoadKTX(*theStream, inFlipY, inFoundation, renderContextType);
} else if (path.endsWith(QLatin1String("astc"), Qt::CaseInsensitive)) {
+ // We need to flip y coordinate in shader as it cannot be done at load time for
+ // compressed textures.
+ bufferManager->SetInvertImageUVCoords(path, inFlipCompressed);
theLoadedImage = LoadASTC(fileName, inFlipY, inFoundation, renderContextType);
} else {
- qCWarning(INTERNAL_ERROR, "Unrecognized image extension: %s", qPrintable(inPath));
+ qCWarning(INTERNAL_ERROR, "Unrecognized image extension: %s", qPrintable(path));
}
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
index 8d65c1f..62408f3 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
@@ -152,11 +152,12 @@ namespace render {
STextureData DecompressDXTImage(int inMipMapIdx, STextureData *inOptLastImage = NULL);
void ReleaseDecompressedTexture(STextureData inImage);
+ // Path must have been resolved or contain actual file or image id
static SLoadedTexture *Load(const QString &inPath, NVFoundationBase &inAllocator,
IInputStreamFactory &inFactory, bool inFlipY = true,
+ bool inFlipCompressed = false,
NVRenderContextType renderContextType
= NVRenderContextValues::NullContext,
- bool preferKTX = false,
IBufferManager *bufferManager = nullptr);
static SLoadedTexture *LoadDDS(IInStream &inStream, QT3DSI32 flipVertical,
NVFoundationBase &fnd,
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureHDR.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureHDR.cpp
index defff29..60e242d 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureHDR.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureHDR.cpp
@@ -145,18 +145,23 @@ static void decrunchScanline(FreeImageIO *io, fi_handle handle, RGBE *scanline,
static void decodeScanlineToTexture(RGBE *scanline, int width, void *outBuf, QT3DSU32 offset,
NVRenderTextureFormats::Enum inFormat)
{
- float rgbaF32[4];
-
- for (int i = 0; i < width; ++i) {
- rgbaF32[R] = convertComponent(scanline[i][E], scanline[i][R]);
- rgbaF32[G] = convertComponent(scanline[i][E], scanline[i][G]);
- rgbaF32[B] = convertComponent(scanline[i][E], scanline[i][B]);
- rgbaF32[3] = 1.0f;
-
- QT3DSU8 *target = reinterpret_cast<QT3DSU8 *>(outBuf);
- target += offset;
- NVRenderTextureFormats::encodeToPixel(
- rgbaF32, target, i * NVRenderTextureFormats::getSizeofFormat(inFormat), inFormat);
+
+ QT3DSU8 *target = reinterpret_cast<QT3DSU8 *>(outBuf);
+ target += offset;
+
+ if (inFormat == NVRenderTextureFormats::RGBE8) {
+ memcpy(target, scanline, size_t(4 * width));
+ } else {
+ float rgbaF32[4];
+ for (int i = 0; i < width; ++i) {
+ rgbaF32[R] = convertComponent(scanline[i][E], scanline[i][R]);
+ rgbaF32[G] = convertComponent(scanline[i][E], scanline[i][G]);
+ rgbaF32[B] = convertComponent(scanline[i][E], scanline[i][B]);
+ rgbaF32[3] = 1.0f;
+
+ NVRenderTextureFormats::encodeToPixel(
+ rgbaF32, target, i * NVRenderTextureFormats::getSizeofFormat(inFormat), inFormat);
+ }
}
}
@@ -242,14 +247,6 @@ SLoadedTexture *SLoadedTexture::LoadHDR(ISeekableIOStream &inStream, NVFoundatio
{
FreeImageIO theIO(inFnd.getAllocator(), inFnd);
SLoadedTexture *retval = nullptr;
- if (renderContextType == qt3ds::render::NVRenderContextValues::GLES2)
- retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBA8);
- else
- retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBA16F);
-
-
- // Let's just assume we don't support this just yet.
- // if ( retval )
- // retval->FreeImagePostProcess( inFlipY );
+ retval = DoLoadHDR(&theIO, &inStream, NVRenderTextureFormats::RGBE8);
return retval;
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp
index aea4543..93ad2d4 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTextureKTX.cpp
@@ -64,6 +64,8 @@ static inline int blockSizeForTextureFormat(int format)
static inline int runtimeFormat(quint32 internalFormat)
{
switch (internalFormat) {
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ return NVRenderTextureFormats::RGBA8_ETC2_EAC;
case QOpenGLTexture::RGB8_ETC1:
return NVRenderTextureFormats::RGB8_ETC1;
case QOpenGLTexture::RGB8_ETC2:
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.cpp
index 023964f..c9352dc 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.cpp
@@ -38,6 +38,213 @@ using namespace qt3ds;
using namespace qt3ds::render;
using namespace qt3ds::foundation;
+
+struct M8E8
+{
+ quint8 m;
+ quint8 e;
+ M8E8() : m(0), e(0){
+ }
+ M8E8(const float val) {
+ float l2 = 1.f + floor(log2f(val));
+ float mm = val / powf(2.f, l2);
+ m = quint8(mm * 255.f);
+ e = quint8(l2 + 128);
+ }
+ M8E8(const float val, quint8 exp) {
+ if (val <= 0) {
+ m = e = 0;
+ return;
+ }
+ float mm = val / powf(2.f, exp - 128);
+ m = quint8(mm * 255.f);
+ e = exp;
+ }
+};
+
+void NVRenderTextureFormats::decodeToFloat(void *inPtr, QT3DSU32 byteOfs, float *outPtr,
+ NVRenderTextureFormats::Enum inFmt)
+{
+ outPtr[0] = 0.0f;
+ outPtr[1] = 0.0f;
+ outPtr[2] = 0.0f;
+ outPtr[3] = 0.0f;
+ QT3DSU8 *src = reinterpret_cast<QT3DSU8 *>(inPtr);
+ switch (inFmt) {
+ case Alpha8:
+ outPtr[0] = ((float)src[byteOfs]) / 255.0f;
+ break;
+
+ case Luminance8:
+ case LuminanceAlpha8:
+ case R8:
+ case RG8:
+ case RGB8:
+ case RGBA8:
+ case SRGB8:
+ case SRGB8A8:
+ for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
+ float val = ((float)src[byteOfs + i]) / 255.0f;
+ outPtr[i] = (i < 3) ? powf(val, 0.4545454545f) : val;
+ }
+ break;
+ case RGBE8:
+ {
+ float pwd = powf(2.0f, int(src[byteOfs + 3]) - 128);
+ outPtr[0] = float(src[byteOfs + 0]) * pwd / 255.0;
+ outPtr[1] = float(src[byteOfs + 1]) * pwd / 255.0;
+ outPtr[2] = float(src[byteOfs + 2]) * pwd / 255.0;
+ outPtr[3] = 1.0f;
+ } break;
+
+ case R32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ break;
+ case RG32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ break;
+ case RGBA32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
+ outPtr[3] = reinterpret_cast<float *>(src + byteOfs)[3];
+ break;
+ case RGB32F:
+ outPtr[0] = reinterpret_cast<float *>(src + byteOfs)[0];
+ outPtr[1] = reinterpret_cast<float *>(src + byteOfs)[1];
+ outPtr[2] = reinterpret_cast<float *>(src + byteOfs)[2];
+ break;
+
+ case R16F:
+ case RG16F:
+ case RGBA16F:
+ for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
+ // NOTE : This only works on the assumption that we don't have any denormals,
+ // Infs or NaNs.
+ // Every pixel in our source image should be "regular"
+ QT3DSU16 h = reinterpret_cast<QT3DSU16 *>(src + byteOfs)[i];
+ QT3DSU32 sign = (h & 0x8000) << 16;
+ QT3DSU32 exponent = (((((h & 0x7c00) >> 10) - 15) + 127) << 23);
+ QT3DSU32 mantissa = ((h & 0x3ff) << 13);
+ QT3DSU32 result = sign | exponent | mantissa;
+
+ if (h == 0 || h == 0x8000)
+ result = 0;
+ qt3ds::intrinsics::memCopy(reinterpret_cast<QT3DSU32 *>(outPtr) + i, &result, 4);
+ }
+ break;
+
+ case R11G11B10:
+ // place holder
+ QT3DS_ASSERT(false);
+ break;
+
+ default:
+ outPtr[0] = 0.0f;
+ outPtr[1] = 0.0f;
+ outPtr[2] = 0.0f;
+ outPtr[3] = 0.0f;
+ break;
+ }
+}
+
+void NVRenderTextureFormats::encodeToPixel(float *inPtr, void *outPtr, QT3DSU32 byteOfs,
+ NVRenderTextureFormats::Enum inFmt)
+{
+ QT3DSU8 *dest = reinterpret_cast<QT3DSU8 *>(outPtr);
+ switch (inFmt) {
+ case NVRenderTextureFormats::Alpha8:
+ dest[byteOfs] = QT3DSU8(inPtr[0] * 255.0f);
+ break;
+
+ case Luminance8:
+ case LuminanceAlpha8:
+ case R8:
+ case RG8:
+ case RGB8:
+ case RGBA8:
+ case SRGB8:
+ case SRGB8A8:
+ for (QT3DSU32 i = 0; i < NVRenderTextureFormats::getSizeofFormat(inFmt); ++i) {
+ inPtr[i] = (inPtr[i] > 1.0f) ? 1.0f : inPtr[i];
+ if (i < 3)
+ dest[byteOfs + i] = QT3DSU8(powf(inPtr[i], 2.2f) * 255.0f);
+ else
+ dest[byteOfs + i] = QT3DSU8(inPtr[i] * 255.0f);
+ }
+ break;
+ case RGBE8:
+ {
+ float max = qMax(inPtr[0], qMax(inPtr[1], inPtr[2]));
+ M8E8 ex(max);
+ M8E8 a(inPtr[0], ex.e);
+ M8E8 b(inPtr[1], ex.e);
+ M8E8 c(inPtr[2], ex.e);
+ quint8 *dst = reinterpret_cast<quint8 *>(outPtr) + byteOfs;
+ dst[0] = a.m;
+ dst[1] = b.m;
+ dst[2] = c.m;
+ dst[3] = ex.e;
+ } break;
+
+ case R32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ break;
+ case RG32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ break;
+ case RGBA32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
+ reinterpret_cast<float *>(dest + byteOfs)[3] = inPtr[3];
+ break;
+ case RGB32F:
+ reinterpret_cast<float *>(dest + byteOfs)[0] = inPtr[0];
+ reinterpret_cast<float *>(dest + byteOfs)[1] = inPtr[1];
+ reinterpret_cast<float *>(dest + byteOfs)[2] = inPtr[2];
+ break;
+
+ case R16F:
+ case RG16F:
+ case RGBA16F:
+ for (QT3DSU32 i = 0; i < (NVRenderTextureFormats::getSizeofFormat(inFmt) >> 1); ++i) {
+ // NOTE : This also has the limitation of not handling infs, NaNs and
+ // denormals, but it should be sufficient for our purposes.
+ if (inPtr[i] > 65519.0f)
+ inPtr[i] = 65519.0f;
+ if (fabs(inPtr[i]) < 6.10352E-5f)
+ inPtr[i] = 0.0f;
+ QT3DSU32 f = reinterpret_cast<QT3DSU32 *>(inPtr)[i];
+ QT3DSU32 sign = (f & 0x80000000) >> 16;
+ QT3DSI32 exponent = (f & 0x7f800000) >> 23;
+ QT3DSU32 mantissa = (f >> 13) & 0x3ff;
+ exponent = exponent - 112;
+ if (exponent > 31)
+ exponent = 31;
+ if (exponent < 0)
+ exponent = 0;
+ exponent = exponent << 10;
+ reinterpret_cast<QT3DSU16 *>(dest + byteOfs)[i] = QT3DSU16(sign | exponent | mantissa);
+ }
+ break;
+
+ case R11G11B10:
+ // place holder
+ QT3DS_ASSERT(false);
+ break;
+
+ default:
+ dest[byteOfs] = 0;
+ dest[byteOfs + 1] = 0;
+ dest[byteOfs + 2] = 0;
+ dest[byteOfs + 3] = 0;
+ break;
+ }
+}
+
Qt3DSRenderPrefilterTexture::Qt3DSRenderPrefilterTexture(NVRenderContext *inNVRenderContext,
QT3DSI32 inWidth, QT3DSI32 inHeight,
NVRenderTexture2D &inTexture2D,
@@ -66,7 +273,7 @@ Qt3DSRenderPrefilterTexture::Create(NVRenderContext *inNVRenderContext, QT3DSI32
NVRenderTextureFormats::Enum inDestFormat,
qt3ds::NVFoundationBase &inFnd)
{
- Qt3DSRenderPrefilterTexture *theBSDFMipMap = NULL;
+ Qt3DSRenderPrefilterTexture *theBSDFMipMap = nullptr;
if (inNVRenderContext->IsComputeSupported()) {
theBSDFMipMap = QT3DS_NEW(inFnd.getAllocator(), Qt3DSRenderPrefilterTextureCompute)(
@@ -128,14 +335,13 @@ Qt3DSRenderPrefilterTextureCPU::CreateBsdfMipLevel(STextureData &inCurMipLevel,
int newHeight = height >> 1;
newWidth = newWidth >= 1 ? newWidth : 1;
newHeight = newHeight >= 1 ? newHeight : 1;
+ const QT3DSU32 size = NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
if (inCurMipLevel.data) {
retval = inCurMipLevel;
- retval.dataSizeInBytes =
- newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ retval.dataSizeInBytes = newWidth * newHeight * size;
} else {
- retval.dataSizeInBytes =
- newWidth * newHeight * NVRenderTextureFormats::getSizeofFormat(inPrevMipLevel.format);
+ retval.dataSizeInBytes = newWidth * newHeight * size;
retval.format = inPrevMipLevel.format; // inLoadedImage.format;
retval.data = m_Foundation.getAllocator().allocate(
retval.dataSizeInBytes, "Bsdf Scaled Image Data", __FILE__, __LINE__);
@@ -155,26 +361,20 @@ Qt3DSRenderPrefilterTextureCPU::CreateBsdfMipLevel(STextureData &inCurMipLevel,
getWrappedCoords(sampleX, sampleY, width, height);
// Cauchy filter (this is simply because it's the easiest to evaluate, and
- // requires no complex
- // functions).
+ // requires no complex functions).
float filterPdf = 1.f / (1.f + float(sx * sx + sy * sy) * 2.f);
// With FP HDR formats, we're not worried about intensity loss so much as
// unnecessary energy gain,
// whereas with LDR formats, the fear with a continuous normalization factor is
- // that we'd lose
- // intensity and saturation as well.
- filterPdf /= (NVRenderTextureFormats::getSizeofFormat(retval.format) >= 8)
- ? 4.71238898f
- : 4.5403446f;
- // filterPdf /= 4.5403446f; // Discrete normalization factor
- // filterPdf /= 4.71238898f; // Continuous normalization factor
+ // that we'd lose intensity and saturation as well.
+ filterPdf /= (size >= 8) ? 4.71238898f : 4.5403446f;
+ // filterPdf /= 4.5403446f; // Discrete normalization factor
+ // filterPdf /= 4.71238898f; // Continuous normalization factor
float curPix[4];
- QT3DSI32 byteOffset = (sampleY * width + sampleX)
- * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ QT3DSI32 byteOffset = (sampleY * width + sampleX) * size;
if (byteOffset < 0) {
sampleY = height + sampleY;
- byteOffset = (sampleY * width + sampleX)
- * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ byteOffset = (sampleY * width + sampleX) * size;
}
NVRenderTextureFormats::decodeToFloat(inPrevMipLevel.data, byteOffset, curPix,
@@ -187,8 +387,7 @@ Qt3DSRenderPrefilterTextureCPU::CreateBsdfMipLevel(STextureData &inCurMipLevel,
}
}
- QT3DSU32 newIdx =
- (y * newWidth + x) * NVRenderTextureFormats::getSizeofFormat(retval.format);
+ QT3DSU32 newIdx = (y * newWidth + x) * size;
NVRenderTextureFormats::encodeToPixel(accumVal, retval.data, newIdx, retval.format);
}
@@ -205,6 +404,7 @@ void Qt3DSRenderPrefilterTextureCPU::Build(void *inTextureData, QT3DSI32 inTextu
m_SizeOfInternalFormat = NVRenderTextureFormats::getSizeofFormat(m_InternalFormat);
m_InternalNoOfComponent = NVRenderTextureFormats::getNumberOfComponent(m_InternalFormat);
+ m_Texture2D.SetMaxLevel(m_MaxMipMapLevel);
m_Texture2D.SetTextureData(NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize), 0,
m_Width, m_Height, inFormat, m_DestinationFormat);
@@ -333,7 +533,7 @@ static const char *computeUploadShader(std::string &prog, NVRenderTextureFormats
return prog.c_str();
}
-static const char *computeWorkShader(std::string &prog, bool binESContext)
+static const char *computeWorkShader(std::string &prog, bool binESContext, bool rgbe)
{
if (binESContext) {
prog += "#version 310 es\n"
@@ -358,10 +558,32 @@ static const char *computeWorkShader(std::string &prog, bool binESContext)
" sX = wrapMod( sX, width );\n"
"}\n";
+ if (rgbe) {
+ prog += "vec4 decodeRGBE(in vec4 rgbe)\n"
+ "{\n"
+ " float f = pow(2.0, 255.0 * rgbe.a - 128.0);\n"
+ " return vec4(rgbe.rgb * f, 1.0);\n"
+ "}\n";
+ prog += "vec4 encodeRGBE(in vec4 rgba)\n"
+ "{\n"
+ " float maxMan = max(rgba.r, max(rgba.g, rgba.b));\n"
+ " float maxExp = 1.0 + floor(log2(maxMan));\n"
+ " return vec4(rgba.rgb / pow(2.0, maxExp), (maxExp + 128.0) / 255.0);\n"
+ "}\n";
+ }
+
prog += "// Set workgroup layout;\n"
- "layout (local_size_x = 16, local_size_y = 16) in;\n\n"
+ "layout (local_size_x = 16, local_size_y = 16) in;\n\n";
+ if (rgbe) {
+ prog +=
+ "layout (rgba8, binding = 1) readonly uniform image2D inputImage;\n\n"
+ "layout (rgba8, binding = 2) writeonly uniform image2D outputImage;\n\n";
+ } else {
+ prog +=
"layout (rgba16f, binding = 1) readonly uniform image2D inputImage;\n\n"
- "layout (rgba16f, binding = 2) writeonly uniform image2D outputImage;\n\n"
+ "layout (rgba16f, binding = 2) writeonly uniform image2D outputImage;\n\n";
+ }
+ prog +=
"void main()\n"
"{\n"
" int prevWidth = int(gl_NumWorkGroups.x) << 1;\n"
@@ -377,19 +599,31 @@ static const char *computeWorkShader(std::string &prog, bool binESContext)
" int sampleX = sx + (int(gl_GlobalInvocationID.x) << 1);\n"
" int sampleY = sy + (int(gl_GlobalInvocationID.y) << 1);\n"
" getWrappedCoords(sampleX, sampleY, prevWidth, prevHeight);\n"
- " if ((sampleY * prevWidth + sampleX) < 0 )\n"
+ " if ((sampleY * prevWidth + sampleX) < 0 )\n"
" sampleY = prevHeight + sampleY;\n"
" ivec2 pos = ivec2(sampleX, sampleY);\n"
- " vec4 value = imageLoad(inputImage, pos);\n"
- " float filterPdf = 1.0 / ( 1.0 + float(sx*sx + sy*sy)*2.0 );\n"
+ " vec4 value = imageLoad(inputImage, pos);\n";
+
+ if (rgbe) {
+ prog +=
+ " value = decodeRGBE(value);\n";
+ }
+
+ prog += " float filterPdf = 1.0 / ( 1.0 + float(sx*sx + sy*sy)*2.0 );\n"
" filterPdf /= 4.71238898;\n"
" accumVal[0] += filterPdf * value.r;\n"
- " accumVal[1] += filterPdf * value.g;\n"
- " accumVal[2] += filterPdf * value.b;\n"
- " accumVal[3] += filterPdf * value.a;\n"
+ " accumVal[1] += filterPdf * value.g;\n"
+ " accumVal[2] += filterPdf * value.b;\n"
+ " accumVal[3] += filterPdf * value.a;\n"
" }\n"
- " }\n"
- " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), accumVal );\n"
+ " }\n";
+
+ if (rgbe) {
+ prog +=
+ " accumVal = encodeRGBE(accumVal);\n";
+ }
+
+ prog += " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), accumVal );\n"
"}\n";
return prog.c_str();
@@ -422,33 +656,46 @@ Qt3DSRenderPrefilterTextureCompute::Qt3DSRenderPrefilterTextureCompute(
NVFoundationBase &inFnd)
: Qt3DSRenderPrefilterTexture(inNVRenderContext, inWidth, inHeight, inTexture2D, inDestFormat,
inFnd)
- , m_BSDFProgram(NULL)
- , m_UploadProgram_RGBA8(NULL)
- , m_UploadProgram_RGB8(NULL)
- , m_Level0Tex(NULL)
+ , m_BSDFProgram(nullptr)
+ , m_BSDF_RGBE_Program(nullptr)
+ , m_UploadProgram_RGBA8(nullptr)
+ , m_UploadProgram_RGB8(nullptr)
+ , m_Level0Tex(nullptr)
, m_TextureCreated(false)
{
}
Qt3DSRenderPrefilterTextureCompute::~Qt3DSRenderPrefilterTextureCompute()
{
- m_UploadProgram_RGB8 = NULL;
- m_UploadProgram_RGBA8 = NULL;
- m_BSDFProgram = NULL;
- m_Level0Tex = NULL;
+ m_BSDF_RGBE_Program = nullptr;
+ m_UploadProgram_RGB8 = nullptr;
+ m_UploadProgram_RGBA8 = nullptr;
+ m_BSDFProgram = nullptr;
+ m_Level0Tex = nullptr;
}
-void Qt3DSRenderPrefilterTextureCompute::createComputeProgram(NVRenderContext *context)
+NVRenderShaderProgram *Qt3DSRenderPrefilterTextureCompute::createComputeProgram(
+ NVRenderContext *context, NVRenderTextureFormats::Enum format)
{
std::string computeProg;
- if (!m_BSDFProgram) {
+ if (!m_BSDFProgram && format != NVRenderTextureFormats::RGBE8) {
m_BSDFProgram = context
->CompileComputeSource(
"Compute BSDF mipmap shader",
- toRef(computeWorkShader(computeProg, isGLESContext(context))))
+ toRef(computeWorkShader(computeProg, isGLESContext(context), false)))
+ .mShader;
+ return m_BSDFProgram;
+ }
+ if (!m_BSDF_RGBE_Program && format == NVRenderTextureFormats::RGBE8) {
+ m_BSDF_RGBE_Program = context
+ ->CompileComputeSource(
+ "Compute BSDF RGBE mipmap shader",
+ toRef(computeWorkShader(computeProg, isGLESContext(context), true)))
.mShader;
+ return m_BSDF_RGBE_Program;
}
+ return nullptr;
}
NVRenderShaderProgram *Qt3DSRenderPrefilterTextureCompute::getOrCreateUploadComputeProgram(
@@ -496,7 +743,7 @@ void Qt3DSRenderPrefilterTextureCompute::CreateLevel0Tex(void *inTextureData, QT
theWidth = (m_Width * 3) / 4;
}
- if (m_Level0Tex == NULL) {
+ if (m_Level0Tex == nullptr) {
m_Level0Tex = m_NVRenderContext->CreateTexture2D();
m_Level0Tex->SetTextureStorage(1, theWidth, m_Height, theFormat, theFormat,
NVDataRef<QT3DSU8>((QT3DSU8 *)inTextureData, inTextureDataSize));
@@ -510,6 +757,7 @@ void Qt3DSRenderPrefilterTextureCompute::Build(void *inTextureData, QT3DSI32 inT
NVRenderTextureFormats::Enum inFormat)
{
bool needMipUpload = (inFormat != m_DestinationFormat);
+ NVRenderShaderProgram *program = nullptr;
// re-upload data
if (!m_TextureCreated) {
m_Texture2D.SetTextureStorage(
@@ -519,9 +767,9 @@ void Qt3DSRenderPrefilterTextureCompute::Build(void *inTextureData, QT3DSI32 inT
m_Texture2D.addRef();
// create a compute shader (if not aloread done) which computes the BSDF mipmaps for this
// texture
- createComputeProgram(m_NVRenderContext);
+ program = createComputeProgram(m_NVRenderContext, inFormat);
- if (!m_BSDFProgram) {
+ if (!program) {
QT3DS_ASSERT(false);
return;
}
@@ -575,19 +823,19 @@ void Qt3DSRenderPrefilterTextureCompute::Build(void *inTextureData, QT3DSI32 inT
int width = m_Width >> 1;
int height = m_Height >> 1;
- m_NVRenderContext->SetActiveShader(m_BSDFProgram);
+ m_NVRenderContext->SetActiveShader(program);
for (int i = 1; i <= m_MaxMipMapLevel; ++i) {
theOutputImage->SetTextureLevel(i);
NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedOutputImage("outputImage",
- *m_BSDFProgram);
+ *program);
theCachedOutputImage.Set(theOutputImage);
theInputImage->SetTextureLevel(i - 1);
NVRenderCachedShaderProperty<NVRenderImage2D *> theCachedinputImage("inputImage",
- *m_BSDFProgram);
+ *program);
theCachedinputImage.Set(theInputImage);
- m_NVRenderContext->DispatchCompute(m_BSDFProgram, width, height, 1);
+ m_NVRenderContext->DispatchCompute(program, width, height, 1);
width = width > 2 ? width >> 1 : 1;
height = height > 2 ? height >> 1 : 1;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.h b/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.h
index e633eb1..e646443 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderPrefilterTexture.h
@@ -113,15 +113,16 @@ namespace render {
NVRenderTextureFormats::Enum inFormat);
NVScopedRefCounted<NVRenderShaderProgram> m_BSDFProgram;
+ NVScopedRefCounted<NVRenderShaderProgram> m_BSDF_RGBE_Program;
NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGBA8;
NVScopedRefCounted<NVRenderShaderProgram> m_UploadProgram_RGB8;
NVScopedRefCounted<NVRenderTexture2D> m_Level0Tex;
bool m_TextureCreated;
- void createComputeProgram(NVRenderContext *context);
- NVRenderShaderProgram *
- getOrCreateUploadComputeProgram(NVRenderContext *context,
- NVRenderTextureFormats::Enum inFormat);
+ NVRenderShaderProgram *createComputeProgram(
+ NVRenderContext *context, NVRenderTextureFormats::Enum format);
+ NVRenderShaderProgram *getOrCreateUploadComputeProgram(
+ NVRenderContext *context, NVRenderTextureFormats::Enum inFormat);
};
}
}
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.cpp
index 3593688..68f90fb 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.cpp
@@ -83,7 +83,7 @@ struct SResourceManager : public IResourceManager
m_FreeFrameBuffers.pop_back();
return retval;
}
- void Release(NVRenderFrameBuffer &inBuffer) override
+ void Release(NVRenderFrameBuffer &inBuffer, bool forceRelease) override
{
if (inBuffer.HasAnyAttachment()) {
// Ensure the framebuffer has no attachments.
@@ -116,7 +116,10 @@ struct SResourceManager : public IResourceManager
eastl::find(m_FreeFrameBuffers.begin(), m_FreeFrameBuffers.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeFrameBuffers.end());
#endif
- m_FreeFrameBuffers.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeFrameBuffers.push_back(&inBuffer);
}
virtual NVRenderRenderBuffer *
@@ -151,14 +154,17 @@ struct SResourceManager : public IResourceManager
m_AllocatedObjects.push_back(theBuffer);
return theBuffer;
}
- void Release(NVRenderRenderBuffer &inBuffer) override
+ void Release(NVRenderRenderBuffer &inBuffer, bool forceRelease) override
{
#ifdef _DEBUG
nvvector<NVRenderRenderBuffer *>::iterator theFind =
eastl::find(m_FreeRenderBuffers.begin(), m_FreeRenderBuffers.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeRenderBuffers.end());
#endif
- m_FreeRenderBuffers.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeRenderBuffers.push_back(&inBuffer);
}
NVRenderTexture2D *SetupAllocatedTexture(NVRenderTexture2D &inTexture)
{
@@ -211,14 +217,17 @@ struct SResourceManager : public IResourceManager
m_AllocatedObjects.push_back(theTexture);
return SetupAllocatedTexture(*theTexture);
}
- void Release(NVRenderTexture2D &inBuffer) override
+ void Release(NVRenderTexture2D &inBuffer, bool forceRelease) override
{
#ifdef _DEBUG
nvvector<NVRenderTexture2D *>::iterator theFind =
eastl::find(m_FreeTextures.begin(), m_FreeTextures.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeTextures.end());
#endif
- m_FreeTextures.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeTextures.push_back(&inBuffer);
}
NVRenderTexture2DArray *AllocateTexture2DArray(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inSlices,
@@ -273,14 +282,17 @@ struct SResourceManager : public IResourceManager
return theTexture;
}
- void Release(NVRenderTexture2DArray &inBuffer) override
+ void Release(NVRenderTexture2DArray &inBuffer, bool forceRelease) override
{
#ifdef _DEBUG
nvvector<NVRenderTexture2DArray *>::iterator theFind =
eastl::find(m_FreeTexArrays.begin(), m_FreeTexArrays.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeTexArrays.end());
#endif
- m_FreeTexArrays.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeTexArrays.push_back(&inBuffer);
}
NVRenderTextureCube *AllocateTextureCube(QT3DSU32 inWidth, QT3DSU32 inHeight,
@@ -356,14 +368,17 @@ struct SResourceManager : public IResourceManager
return theTexture;
}
- void Release(NVRenderTextureCube &inBuffer) override
+ void Release(NVRenderTextureCube &inBuffer, bool forceRelease) override
{
#ifdef _DEBUG
nvvector<NVRenderTextureCube *>::iterator theFind =
eastl::find(m_FreeTexCubes.begin(), m_FreeTexCubes.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeTexCubes.end());
#endif
- m_FreeTexCubes.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeTexCubes.push_back(&inBuffer);
}
NVRenderImage2D *AllocateImage2D(NVRenderTexture2D *inTexture,
@@ -383,14 +398,17 @@ struct SResourceManager : public IResourceManager
return retval;
}
- void Release(NVRenderImage2D &inBuffer) override
+ void Release(NVRenderImage2D &inBuffer, bool forceRelease) override
{
#ifdef _DEBUG
nvvector<NVRenderImage2D *>::iterator theFind =
eastl::find(m_FreeImages.begin(), m_FreeImages.end(), &inBuffer);
QT3DS_ASSERT(theFind == m_FreeImages.end());
#endif
- m_FreeImages.push_back(&inBuffer);
+ if (forceRelease)
+ RemoveObjectAllocation(&inBuffer);
+ else
+ m_FreeImages.push_back(&inBuffer);
}
NVRenderContext &GetRenderContext() override { return *m_RenderContext; }
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.h b/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.h
index 675d644..3d6d59b 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderResourceManager.h
@@ -46,29 +46,31 @@ namespace render {
public:
virtual NVRenderFrameBuffer *AllocateFrameBuffer() = 0;
- virtual void Release(NVRenderFrameBuffer &inBuffer) = 0;
virtual NVRenderRenderBuffer *
AllocateRenderBuffer(QT3DSU32 inWidth, QT3DSU32 inHeight,
NVRenderRenderBufferFormats::Enum inBufferFormat) = 0;
- virtual void Release(NVRenderRenderBuffer &inBuffer) = 0;
+
virtual NVRenderTexture2D *AllocateTexture2D(QT3DSU32 inWidth, QT3DSU32 inHeight,
NVRenderTextureFormats::Enum inTextureFormat,
QT3DSU32 inSampleCount = 1,
bool immutable = false) = 0;
- virtual void Release(NVRenderTexture2D &inBuffer) = 0;
virtual NVRenderTexture2DArray *
AllocateTexture2DArray(QT3DSU32 inWidth, QT3DSU32 inHeight, QT3DSU32 inSlices,
NVRenderTextureFormats::Enum inTextureFormat,
QT3DSU32 inSampleCount = 1) = 0;
- virtual void Release(NVRenderTexture2DArray &inBuffer) = 0;
virtual NVRenderTextureCube *
AllocateTextureCube(QT3DSU32 inWidth, QT3DSU32 inHeight,
NVRenderTextureFormats::Enum inTextureFormat,
QT3DSU32 inSampleCount = 1) = 0;
- virtual void Release(NVRenderTextureCube &inBuffer) = 0;
virtual NVRenderImage2D *AllocateImage2D(NVRenderTexture2D *inTexture,
NVRenderImageAccessType::Enum inAccess) = 0;
- virtual void Release(NVRenderImage2D &inBuffer) = 0;
+
+ virtual void Release(NVRenderFrameBuffer &inBuffer, bool forceRelease = false) = 0;
+ virtual void Release(NVRenderRenderBuffer &inBuffer, bool forceRelease = false) = 0;
+ virtual void Release(NVRenderTexture2D &inBuffer, bool forceRelease = false) = 0;
+ virtual void Release(NVRenderTexture2DArray &inBuffer, bool forceRelease = false) = 0;
+ virtual void Release(NVRenderTextureCube &inBuffer, bool forceRelease = false) = 0;
+ virtual void Release(NVRenderImage2D &inBuffer, bool forceRelease = false) = 0;
virtual NVRenderContext &GetRenderContext() = 0;
virtual void DestroyFreeSizedResources() = 0;
diff --git a/src/system/Qt3DSHash.h b/src/system/Qt3DSHash.h
index 8baa2db..b074d9c 100644
--- a/src/system/Qt3DSHash.h
+++ b/src/system/Qt3DSHash.h
@@ -30,6 +30,7 @@
#pragma once
#include "Qt3DSConfig.h"
+#include <qstring.h>
//==============================================================================
// Namespace
@@ -77,6 +78,37 @@ public: // Static utility
return theHash;
}
+ static TStringHash HashString(const QString &inString)
+ {
+ TStringHash theHash = 0;
+ INT32 theCount = 0;
+ for (auto theChar : inString) {
+ if (theCount == HASH_LIMIT)
+ break;
+ theHash = theChar.toLatin1() + (theHash << 6) + (theHash << 16) - theHash;
+ ++theCount;
+ }
+ theHash = (theHash << 6) + (theHash << 16) - theHash;
+
+ return theHash;
+ }
+
+ static TStringHash HashString(const QString &inString, int begin, int end)
+ {
+ TStringHash theHash = 0;
+ INT32 theCount = 0;
+ for (int i = begin; i < end; ++i) {
+ if (theCount == HASH_LIMIT)
+ break;
+ theHash = inString.at(i).toLatin1() + (theHash << 6) + (theHash << 16) - theHash;
+ ++theCount;
+ }
+ theHash = (theHash << 6) + (theHash << 16) - theHash;
+
+ return theHash;
+ }
+
+
//==============================================================================
/**
* 31-bit hash with MSB set to 0
@@ -100,6 +132,11 @@ public: // Static utility
{
return HashString(inString) & 0x03ffffff;
}
+
+ static TAttributeHash HashAttribute(const QString &inString)
+ {
+ return HashString(inString) & 0x03ffffff;
+ }
};
} // namespace Q3DStudio
diff --git a/src/uipparser/Qt3DSIPresentation.h b/src/uipparser/Qt3DSIPresentation.h
index a9d3644..982d4c7 100644
--- a/src/uipparser/Qt3DSIPresentation.h
+++ b/src/uipparser/Qt3DSIPresentation.h
@@ -153,6 +153,9 @@ public: // Event Callbacks
public: // FrameData access
virtual CPresentationFrameData &GetFrameData() = 0;
+
+ virtual void setUIPVersion(int version) = 0;
+ virtual int getUIPVersion() const = 0;
};
} // namespace Q3DStudio
diff --git a/src/uipparser/Qt3DSUIPParser.h b/src/uipparser/Qt3DSUIPParser.h
index 7b4fc3f..c740609 100644
--- a/src/uipparser/Qt3DSUIPParser.h
+++ b/src/uipparser/Qt3DSUIPParser.h
@@ -94,6 +94,7 @@ struct UIPElementTypes
Path,
PathAnchorPoint,
PathSubPath,
+ Signal
};
};
@@ -151,7 +152,7 @@ public: // Parse UIP file
// Creation function
static IUIPParser &Create(const QString &inFileName, IRuntimeMetaData &inMetaData,
qt3ds::render::IInputStreamFactory &inStreamFactory,
- qt3ds::foundation::IStringTable &inStrTable);
+ qt3ds::foundation::IStringTable &inStrTable, int &uipVersion);
};
} // namespace Q3DStudio
diff --git a/src/uipparser/Qt3DSUIPParserActionHelper.cpp b/src/uipparser/Qt3DSUIPParserActionHelper.cpp
index ab6d751..68c6be3 100644
--- a/src/uipparser/Qt3DSUIPParserActionHelper.cpp
+++ b/src/uipparser/Qt3DSUIPParserActionHelper.cpp
@@ -341,7 +341,7 @@ void CUIPParserActionHelper::BuildAction(TElement &inElement, UINT32 inEventName
Q3DStudio_ASSERT(theActionCount > 0);
for (UINT32 theActionIndex = 0; theActionIndex < theActionCount; ++theActionIndex) {
INT32 actionId = theAdder.AddAction(
- COMMAND_SETPROPERTY, theProperties[theActionIndex].first.GetNameHash(),
+ COMMAND_SETPROPERTY, theProperties[theActionIndex].first.nameHash(),
theProperties[theActionIndex].second.m_INT32);
if (theActionIndex == 0)
theAddActionIndex = actionId;
diff --git a/src/uipparser/Qt3DSUIPParserImpl.cpp b/src/uipparser/Qt3DSUIPParserImpl.cpp
index 80187bf..923ff26 100644
--- a/src/uipparser/Qt3DSUIPParserImpl.cpp
+++ b/src/uipparser/Qt3DSUIPParserImpl.cpp
@@ -470,7 +470,8 @@ SParseSlideActionEntry *SParseSlideManager::FindAction(SParseSlide &inSlide,
*/
CUIPParserImpl::CUIPParserImpl(const QString &inFileName, IRuntimeMetaData &inMetaData,
IInputStreamFactory &inFactory,
- qt3ds::foundation::IStringTable &inStringTable)
+ qt3ds::foundation::IStringTable &inStringTable,
+ int &uipVersion)
: m_MetaData(inMetaData)
, m_InputStreamFactory(inFactory)
, m_ParseElementManager(inMetaData, inStringTable)
@@ -495,6 +496,9 @@ CUIPParserImpl::CUIPParserImpl(const QString &inFileName, IRuntimeMetaData &inMe
qCCritical(qt3ds::INVALID_OPERATION)
<< "Invalid UIP file: " << inFileName.toLatin1().constData();
}
+ int version = 0;
+ if (m_DOMReader->Att("version", version))
+ uipVersion = version;
}
// Create Helper class
@@ -842,16 +846,19 @@ void CUIPParserImpl::AddFloat4Attribute(TPropertyDescAndValueList &outDescList,
void CUIPParserImpl::AddStringAttribute(IPresentation &inPresentation,
TPropertyDescAndValueList &outDescList,
- CRegisteredString inAttStrName, const char *inValue)
+ CRegisteredString inAttStrName, const char *inValue,
+ bool addSourceAsString)
{
qt3ds::foundation::CStringHandle theString = inPresentation.GetStringTable().GetHandle(inValue);
UVariant theValue;
theValue.m_StringHandle = theString.handle();
outDescList.push_back(
eastl::make_pair(SPropertyDesc(inAttStrName, ATTRIBUTETYPE_STRING), theValue));
- if (CHash::HashAttribute(inAttStrName.c_str()) == Q3DStudio::ATTRIBUTE_SOURCEPATH && inValue
- && *inValue)
+ if ((addSourceAsString
+ || CHash::HashAttribute(inAttStrName.c_str()) == Q3DStudio::ATTRIBUTE_SOURCEPATH)
+ && inValue && *inValue) {
AddSourcePath(inValue, false);
+ }
}
void CUIPParserImpl::AddElementRefAttribute(TPropertyDescAndValueList &outDescList,
@@ -944,7 +951,10 @@ void CUIPParserImpl::GetAttributeList(IPresentation &inPresentation,
const char *theDataPtr = "";
if (!IsTrivial(inValue))
theReader.Read(theDataPtr);
- AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0], theDataPtr);
+ bool addSourceAsString = inAdditionalType
+ == ERuntimeAdditionalMetaDataType::ERuntimeAdditionalMetaDataTypeTexture;
+ AddStringAttribute(inPresentation, outDescList, inPropNameStrs[0], theDataPtr,
+ addSourceAsString);
break;
}
case ERuntimeDataModelDataTypeLong4: {
@@ -1021,7 +1031,7 @@ EElementType GetElementType(const char *inType)
*/
BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &inReader,
qt3ds::runtime::element::SElement *inNewStyleParent,
- bool initInRenderThread)
+ bool initInRenderThread, bool isInsideLayer)
{
IDOMReader::Scope __childScope(inReader);
IScriptBridge *theScriptBridgeQml = inPresentation.GetScriptBridgeQml();
@@ -1046,6 +1056,7 @@ BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &i
UINT32 theLoopTime = 0;
bool isComponent = false;
bool isBehavior = false;
+ bool isChildInsideLayer = isInsideLayer;
// Create SElement
if (AreEqual(theType, "Scene") || AreEqual(theType, "Component")) {
@@ -1055,7 +1066,14 @@ BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &i
Q3DStudio_ASSERT(theLoopTime != 0); // Something is wrong here
isComponent = true;
} else {
- if (AreEqual(theType, "Behavior") && !IsTrivial(theClass)) {
+ if (AreEqual(theType, "Layer")) {
+ isChildInsideLayer = true;
+ } else if ((AreEqual(theType, "Material") || AreEqual(theType, "CustomMaterial")
+ || AreEqual(theType, "Image")) && !isInsideLayer) {
+ // Identify objects outside a Layer object with types of Material, CustomMaterial
+ // or Image to be inside the material container
+ m_materialContainerIds.append(QString::fromUtf8(theId));
+ } else if (AreEqual(theType, "Behavior") && !IsTrivial(theClass)) {
// Find the sourcepath and load the script
++theClass; // remove the '#'
TIdSourcePathMap::iterator theSourcePathIter = m_IdScriptMap.find(theClass);
@@ -1148,7 +1166,7 @@ BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &i
thePath.insert(0, theNode->m_Name);
}
if (thePath.size())
- theNewElem.m_Path = m_ParseElementManager.m_StringTable.RegisterStr(thePath.c_str());
+ theNewElem.setPath(m_ParseElementManager.m_StringTable.RegisterStr(thePath.c_str()));
if (isBehavior) {
if (theFileString.find(".qml") != eastl::string::npos) {
@@ -1156,7 +1174,8 @@ BOOL CUIPParserImpl::LoadSceneGraph(IPresentation &inPresentation, IDOMReader &i
theFileString.c_str(), initInRenderThread);
}
}
- LoadSceneGraph(inPresentation, inReader, &theNewElem, initInRenderThread);
+ LoadSceneGraph(inPresentation, inReader, &theNewElem, initInRenderThread,
+ isChildInsideLayer);
}
return true;
@@ -1203,7 +1222,8 @@ void CUIPParserImpl::CacheGraphRequiredAttributes(qt3dsdm::IDOMReader &inReader)
m_ParseElementManager.MarkAttributeAsReferenced(theData, "observedproperty");
// Behaviors need all attributes possible on the object on them all the time.
- if (AreEqual(theType, "Behavior") || AreEqual(theType, "RenderPlugin")) {
+ if (AreEqual(theType, "Behavior") || AreEqual(theType, "RenderPlugin")
+ || AreEqual(theType, "CustomMaterial")) {
m_ParseElementManager.MarkAllAttributesAsReferenced(theData);
}
@@ -1627,6 +1647,32 @@ BOOL CUIPParserImpl::LoadStateGraph(IPresentation &inPresentation, qt3dsdm::IDOM
}
}
+ // Add source paths of the source materials of the ReferencedMaterials
+ // to the slide source paths
+ for (const auto &slideRefMats : qAsConst(m_referencedMaterialsBySlide)) {
+ const auto &slideKey = slideRefMats.first;
+ const auto &refMats = slideRefMats.second;
+
+ QVector<QString> sourcePathRefs;
+ for (const auto &refMat : refMats) {
+ // CustomMaterials contains their own source paths
+ sourcePathRefs.append(refMat);
+ // Materials have their source paths inside Image objects
+ if (m_imagesByMaterial.contains(refMat))
+ sourcePathRefs.append(m_imagesByMaterial[refMat]);
+ }
+
+ for (const auto &sourcePathRef : qAsConst(sourcePathRefs)) {
+ if (m_sourcePathsById.contains(sourcePathRef)) {
+ const auto &sourcePaths = m_sourcePathsById[sourcePathRef];
+ for (const auto &sourcePath : sourcePaths) {
+ inPresentation.GetSlideSystem().AddSourcePath(slideKey,
+ sourcePath.toUtf8().constData());
+ }
+ }
+ }
+ }
+
return theStatus;
}
@@ -1643,6 +1689,7 @@ BOOL CUIPParserImpl::LoadState(IPresentation &inPresentation, SElement *inCompon
BOOL theResult = true;
ISlideSystem &theBuilder = inPresentation.GetSlideSystem();
+ m_currentSlideReferencedMaterials.clear();
eastl::string theSlideName = GetSlideName(inReader);
@@ -1673,6 +1720,16 @@ BOOL CUIPParserImpl::LoadState(IPresentation &inPresentation, SElement *inCompon
if (theMaxTime != 0)
theBuilder.SetSlideMaxTime((QT3DSU32)theMaxTime);
+ if (!m_currentSlideReferencedMaterials.empty()) {
+ qt3ds::runtime::SSlideKey key;
+ key.m_Component = inComponent;
+ key.m_Index = inSlideIndex;
+ QPair<qt3ds::runtime::SSlideKey, QVector<QString>> pair;
+ pair.first = key;
+ pair.second = m_currentSlideReferencedMaterials;
+ m_referencedMaterialsBySlide.append(pair);
+ }
+
return theResult;
}
@@ -2155,6 +2212,9 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool m
inReader.Att("ref", theRef);
if (theRef && *theRef && theRef[0] == '#')
++theRef;
+
+ bool isInsideMaterialContainer = m_materialContainerIds.contains(theRef);
+
bool isSet = AreEqual(inReader.GetNarrowElementName(), "Set");
const char8_t *sourcepath;
if (inReader.UnregisteredAtt("sourcepath", sourcepath)) {
@@ -2165,21 +2225,53 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool m
ibl = true;
}
if (!IsTrivial(sourcepath) && sourcepath[0] != '#') {
- AddSourcePath(sourcepath, ibl);
- theBuilder.AddSourcePath(sourcepath);
- if (!masterSlide)
+ m_sourcePathsById[QLatin1Char('#') + QString::fromUtf8(theRef)].append(
+ QString::fromUtf8(sourcepath));
+ // Don't add material container assets to the Master Slide source path list
+ if (!isInsideMaterialContainer) {
+ AddSourcePath(sourcepath, ibl);
+ theBuilder.AddSourcePath(sourcepath);
+ }
+ // Add the material container assets to the list of source paths used by slides
+ // other than the Master Slide, so that the assets are not loaded at startup
+ if (!masterSlide || isInsideMaterialContainer)
m_slideSourcePaths.push_back(QString::fromLatin1(sourcepath));
if (AreEqual(inElementData.m_Type.c_str(), "Layer"))
theBuilder.AddSubPresentation(sourcepath);
-
}
}
+
const char8_t *subpres;
if (inReader.UnregisteredAtt("subpresentation", subpres)) {
if (!IsTrivial(subpres))
theBuilder.AddSubPresentation(subpres);
}
+ const char8_t *referencedmaterial;
+ if (inReader.UnregisteredAtt("referencedmaterial", referencedmaterial)) {
+ if (!IsTrivial(referencedmaterial))
+ m_currentSlideReferencedMaterials.append(referencedmaterial);
+ }
+
+ if (strcmp(inElementData.m_Type, "Material") == 0) {
+ eastl::vector<eastl::string> propertyList;
+ m_MetaData.GetInstanceProperties(inElementData.m_Type, inElementData.m_Class,
+ propertyList, false);
+ for (int i = 0; i < propertyList.size(); ++i) {
+ ERuntimeDataModelDataType type = m_MetaData.GetPropertyType(inElementData.m_Type,
+ m_MetaData.Register(propertyList[i].c_str()),
+ inElementData.m_Class);
+ if (type == ERuntimeDataModelDataTypeLong4) {
+ const char8_t *attValue = "";
+ bool hasAtt = inReader.UnregisteredAtt(propertyList[i].c_str(), attValue);
+ if (hasAtt) {
+ m_imagesByMaterial[QLatin1Char('#') + inElementData.m_Id.c_str()]
+ .append(QString::fromUtf8(attValue));
+ }
+ }
+ }
+ }
+
const bool dyn = IsDynamicObject(inElementData.m_Type);
Option<qt3dsdm::SMetaDataCustomMaterial> mat;
Option<qt3dsdm::SMetaDataEffect> eff;
@@ -2226,9 +2318,13 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool m
// Handle dynamic object texture source paths
if (hasAtt && !IsTrivial(theAttValue) && IsDynamicObject(inElementData.m_Type)
&& theIter->second.m_AdditionalType == ERuntimeAdditionalMetaDataTypeTexture) {
- AddSourcePath(theAttValue, false);
- theBuilder.AddSourcePath(theAttValue);
- if (!masterSlide)
+ m_sourcePathsById[QLatin1Char('#') + QString::fromUtf8(theRef)].append(
+ QString::fromUtf8(theAttValue));
+ if (!isInsideMaterialContainer) {
+ AddSourcePath(theAttValue, false);
+ theBuilder.AddSourcePath(theAttValue);
+ }
+ if (!masterSlide || isInsideMaterialContainer)
m_slideSourcePaths.push_back(QString::fromLatin1(theAttValue));
}
if (isSet == false && theIter->second.m_SlideForceFlag == false) {
@@ -2236,7 +2332,7 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool m
for (QT3DSU32 idx = previousListSize, end = theAttributeList.size(); idx < end;
++idx) {
UVariant *theValue = inElementData.m_Element->FindPropertyValue(
- theAttributeList[idx].first.m_Name);
+ theAttributeList[idx].first.name());
if (theValue) {
*theValue = theAttributeList[idx].second;
}
@@ -2251,11 +2347,17 @@ BOOL CUIPParserImpl::LoadSlideElementAttrs(IPresentation &inPresentation, bool m
if (prop.m_DataType == qt3ds::render::NVRenderShaderDataTypes::NVRenderTexture2DPtr) {
const char8_t *theAttValue = "";
bool hasAtt = inReader.UnregisteredAtt(prop.m_Name, theAttValue);
- if (hasAtt && !IsTrivial(theAttValue) ) {
- AddSourcePath(theAttValue, false);
- theBuilder.AddSourcePath(theAttValue);
- if (!masterSlide)
- m_slideSourcePaths.push_back(QString::fromLatin1(theAttValue));
+ if (hasAtt && !IsTrivial(theAttValue)) {
+ if (theAttValue[0] != '#') {
+ m_sourcePathsById[QLatin1Char('#') + QString::fromUtf8(theRef)].append(
+ QString::fromUtf8(theAttValue));
+ if (!isInsideMaterialContainer) {
+ AddSourcePath(theAttValue, false);
+ theBuilder.AddSourcePath(theAttValue);
+ }
+ if (!masterSlide || isInsideMaterialContainer)
+ m_slideSourcePaths.push_back(QString::fromLatin1(theAttValue));
+ }
}
}
}
@@ -2604,6 +2706,9 @@ SElementAndType CUIPParserImpl::GetElementForID(const char *inElementName)
case qt3dsdm::ComposerObjectTypes::Group:
theUIPType = UIPElementTypes::Group;
break;
+ case qt3dsdm::ComposerObjectTypes::Signal:
+ theUIPType = UIPElementTypes::Signal;
+ break;
case qt3dsdm::ComposerObjectTypes::Component:
theUIPType = UIPElementTypes::Component;
break;
@@ -2672,9 +2777,11 @@ IRuntimeMetaData &CUIPParserImpl::GetMetaData()
IUIPParser &IUIPParser::Create(const QString &inFileName, IRuntimeMetaData &inMetaData,
IInputStreamFactory &inFactory,
- qt3ds::foundation::IStringTable &inStrTable)
+ qt3ds::foundation::IStringTable &inStrTable,
+ int &uipVersion)
{
- CUIPParserImpl &retval = *new CUIPParserImpl(inFileName, inMetaData, inFactory, inStrTable);
+ CUIPParserImpl &retval = *new CUIPParserImpl(inFileName, inMetaData, inFactory,
+ inStrTable, uipVersion);
return retval;
}
}
diff --git a/src/uipparser/Qt3DSUIPParserImpl.h b/src/uipparser/Qt3DSUIPParserImpl.h
index f89227b..aef3d10 100644
--- a/src/uipparser/Qt3DSUIPParserImpl.h
+++ b/src/uipparser/Qt3DSUIPParserImpl.h
@@ -430,6 +430,11 @@ protected:
TStringVector m_SourcePathList;
TStringSet m_iblSources;
QVector<QString> m_slideSourcePaths;
+ QVector<QString> m_materialContainerIds;
+ QHash<QString, QVector<QString>> m_imagesByMaterial;
+ QHash<QString, QVector<QString>> m_sourcePathsById;
+ QVector<QString> m_currentSlideReferencedMaterials;
+ QVector<QPair<qt3ds::runtime::SSlideKey, QVector<QString>>> m_referencedMaterialsBySlide;
struct SElementRefCache
{
@@ -522,7 +527,8 @@ protected:
//==============================================================================
public: // Construction
CUIPParserImpl(const QString &inFileName, IRuntimeMetaData &inMetaData,
- IInputStreamFactory &inFactory, qt3ds::foundation::IStringTable &inStringTable);
+ IInputStreamFactory &inFactory, qt3ds::foundation::IStringTable &inStringTable,
+ int &uipVersion);
virtual ~CUIPParserImpl();
public: // Parse UIP file
@@ -554,7 +560,7 @@ protected: // Operation
bool initInRenderThread);
BOOL LoadSceneGraph(IPresentation &inPresentation, qt3dsdm::IDOMReader &inReader,
qt3ds::runtime::element::SElement *inNewStyleParent,
- bool initInRenderThread);
+ bool initInRenderThread, bool isInsideLayer = false);
BOOL LoadLogic(IPresentation &inPresentation, qt3dsdm::IDOMReader &inReader);
BOOL LoadStateGraph(IPresentation &inPresentation, qt3dsdm::IDOMReader &inReader);
@@ -656,7 +662,8 @@ protected:
ERuntimeAdditionalMetaDataType inAdditionalType,
CRegisteredString *inAttStrNames, qt3dsdm::SFloat4 &inValue);
void AddStringAttribute(IPresentation &inPresentation, TPropertyDescAndValueList &outDescList,
- CRegisteredString inAttStrName, const char *inValue);
+ CRegisteredString inAttStrName, const char *inValue,
+ bool addSourceAsString = false);
void AddElementRefAttribute(TPropertyDescAndValueList &outDescList,
CRegisteredString inAttStrName, SElement *inElement);
diff --git a/src/viewer/Qt3DSViewerApp.cpp b/src/viewer/Qt3DSViewerApp.cpp
index a4cec7f..9b5eb8b 100644
--- a/src/viewer/Qt3DSViewerApp.cpp
+++ b/src/viewer/Qt3DSViewerApp.cpp
@@ -427,10 +427,13 @@ bool Q3DSViewerApp::InitializeApp(int winWidth, int winHeight, const QSurfaceFor
qCritical() << m_Impl.m_error;
return false;
}
-
+ QString errors;
bool success = m_Impl.m_view->InitializeGraphics(format, delayedLoading,
initInRenderThread,
- shaderCache);
+ shaderCache, errors);
+ if (!errors.isEmpty())
+ Q_EMIT SigLoadShaderCacheErrors(errors);
+
if (!success) {
m_Impl.m_error = QObject::tr("Viewer launch failure! Failed to load: '%1'").arg(source);
m_Impl.m_error.append("\n");
@@ -476,6 +479,8 @@ void Q3DSViewerApp::connectSignals()
&Q3DSViewerApp::SigElementsCreated);
connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigMaterialsCreated, this,
&Q3DSViewerApp::SigMaterialsCreated);
+ connect(m_Impl.m_view->signalProxy(), &QRuntimeViewSignalProxy::SigFrameDraw, this,
+ &Q3DSViewerApp::SigFrameDraw);
}
void Q3DSViewerApp::finishAsyncInit()
@@ -522,8 +527,9 @@ void Q3DSViewerApp::setupSearchPath(std::vector<std::string> &cmdLineArgs)
//NvFAppendSearchPath(theModuleDirectory.c_str());
}
-void Q3DSViewerApp::Render()
+bool Q3DSViewerApp::Render()
{
+ bool ret = true;
if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine()) {
if (m_Impl.m_appInitSuccessful) {
for (QEvent *e : m_Impl.m_pendingEvents) {
@@ -535,9 +541,10 @@ void Q3DSViewerApp::Render()
HandleController(*m_Impl.m_view);
#endif
- m_Impl.m_view->Render();
+ ret = m_Impl.m_view->Render();
}
}
+ return ret;
}
void Q3DSViewerApp::SaveState()
@@ -867,6 +874,40 @@ double Q3DSViewerApp::GetStereoEyeSeparation() const
return 0;
}
+void Q3DSViewerApp::SetStereoEyeRotation(double rotation)
+{
+ if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine())
+ m_Impl.m_view->GetTegraRenderEngine()->SetStereoEyeRotation(rotation);
+}
+
+double Q3DSViewerApp::GetStereoEyeRotation() const
+{
+ if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine())
+ return m_Impl.m_view->GetTegraRenderEngine()->GetStereoEyeRotation();
+
+ return 0;
+}
+
+void Q3DSViewerApp::SetStereoProgressiveEnabled(bool enabled)
+{
+ if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine())
+ m_Impl.m_view->GetTegraRenderEngine()->SetStereoProgressiveEnabled(enabled);
+}
+
+bool Q3DSViewerApp::GetStereoProgressiveEnabled() const
+{
+ if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine())
+ return m_Impl.m_view->GetTegraRenderEngine()->GetStereoProgressiveEnabled();
+
+ return 0;
+}
+
+void Q3DSViewerApp::SetSkipFramesInterval(int interval)
+{
+ if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine())
+ m_Impl.m_view->GetTegraRenderEngine()->SetSkipFramesInterval(interval);
+}
+
void Q3DSViewerApp::setMatteColor(const QColor &color)
{
if (m_Impl.m_view && m_Impl.m_view->GetTegraRenderEngine()) {
@@ -1059,6 +1100,16 @@ uint Q3DSViewerApp::textureId(const QString &elementPath)
return m_Impl.m_view->textureId(elementPath);
}
+uint Q3DSViewerApp::textureId(const QString &elementPath, QSize &size, GLenum &format)
+{
+ if (!m_Impl.m_view) {
+ size = {};
+ format = GL_INVALID_ENUM;
+ return 0;
+ }
+ return m_Impl.m_view->textureId(elementPath, size, format);
+}
+
Q3DSViewerApp &Q3DSViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer,
QElapsedTimer *startupTimer)
{
diff --git a/src/viewer/Qt3DSViewerApp.h b/src/viewer/Qt3DSViewerApp.h
index 25d2ed7..8b53e85 100644
--- a/src/viewer/Qt3DSViewerApp.h
+++ b/src/viewer/Qt3DSViewerApp.h
@@ -42,6 +42,7 @@
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
#include <QtGui/qsurfaceformat.h>
+#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
class QQmlImageProviderBase;
@@ -257,9 +258,9 @@ public:
/*
* @brief does the actual scene rendering
*
- * @return no return
+ * @return true if the scene needs to be rendered again in next frame
*/
- void Render();
+ bool Render();
/*
* @brief handle keyboard input
@@ -324,6 +325,14 @@ public:
void SetStereoEyeSeparation(double separation);
double GetStereoEyeSeparation() const;
+ void SetStereoEyeRotation(double rotation);
+ double GetStereoEyeRotation() const;
+
+ void SetStereoProgressiveEnabled(bool enabled);
+ bool GetStereoProgressiveEnabled() const;
+
+ void SetSkipFramesInterval(int interval);
+
void setMatteColor(const QColor &color);
void setShowOnScreenStats(bool s);
@@ -498,6 +507,7 @@ public:
void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider);
uint textureId(const QString &elementPath);
+ uint textureId(const QString &elementPath, QSize &size, GLenum &format);
QString error();
@@ -549,6 +559,8 @@ Q_SIGNALS:
void SigDataOutputValueUpdated(const QString &name, const QVariant &newValue);
void SigPresentationReady();
void SigPresentationLoaded();
+ void SigLoadShaderCacheErrors(const QString &errors);
+ void SigFrameDraw();
};
} // end namespace
diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.cpp b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
index f4ab079..fb25739 100644
--- a/tests/auto/runtime/Qt3DSRenderTestBase.cpp
+++ b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
@@ -78,7 +78,7 @@ bool NVRenderTestBase::initializeQt3DSRenderer(QSurfaceFormat format)
{
m_coreFactory = qt3ds::render::IQt3DSRenderFactoryCore::CreateRenderFactoryCore("", m_windowSystem,
m_timeProvider);
- m_factory = m_coreFactory->CreateRenderFactory(format, false);
+ m_factory = m_coreFactory->CreateRenderFactory(format, false, nullptr);
m_rc = m_factory->GetQt3DSRenderContext();
m_renderImpl = new qt3ds::render::Qt3DSRendererImpl(*m_rc);
diff --git a/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
index ccda520..4f9588c 100644
--- a/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
+++ b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
@@ -61,6 +61,8 @@ private slots:
void testBasics();
void testSourceChange_data();
void testSourceChange();
+ void testActivateActions_data();
+ void testActivateActions();
void testSizeChange_data();
void testSizeChange();
void testUpdateInterval_data();
@@ -85,6 +87,8 @@ private slots:
void testMouseInput();
void testDataInput_data();
void testDataInput();
+ void testTextureQuery();
+ void testTextureQuery_data();
private:
QWindow *createWindow(const QSize &size);
@@ -366,6 +370,43 @@ void tst_Q3DSSurfaceViewer::testSourceChange()
checkPixel(m_viewer, Qt::red);
}
+void tst_Q3DSSurfaceViewer::testActivateActions_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testActivateActions()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, ACTIVATEACTIONS);
+ else
+ createOffscreenAndViewer(m_viewer, ACTIVATEACTIONS);
+
+ QSignalSpy spy(m_viewer->presentation(), &Q3DSPresentation::customSignalEmitted);
+
+ QVERIFY(spy.isValid());
+
+ // Wait a bit to prevent grabbing the first image too soon
+ QTest::qWait(100);
+
+ // This presentations sends custom signals at 1000ms and at 3000ms.
+ // At same times it also changes scene color using activate actions.
+ QCOMPARE(spy.count(), 0);
+ QImage image1 = m_viewer->grab();
+
+ QTest::qWait(2000);
+ QCOMPARE(spy.count(), 1);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ QTest::qWait(2000);
+ QCOMPARE(spy.count(), 2);
+ QImage image3 = m_viewer->grab();
+ QVERIFY(image1 == image3);
+}
+
void tst_Q3DSSurfaceViewer::testSizeChange_data()
{
testBasics_data();
@@ -1249,7 +1290,7 @@ void tst_Q3DSSurfaceViewer::testSceneElement()
QCOMPARE(spy1.count(), 6);
QCOMPARE(spy2.count(), 6);
- scene->setCurrentSlideIndex(0);
+ scene->setCurrentSlideIndex(1);
checkPixel(m_viewer, Qt::red);
QCOMPARE(spy1.count(), 7);
@@ -1305,7 +1346,7 @@ void tst_Q3DSSurfaceViewer::testSceneElement()
QCOMPARE(spy2.count(), 11);
// Back to first slide for further tests
- scene->setCurrentSlideIndex(0);
+ scene->setCurrentSlideIndex(1);
checkPixel(m_viewer, Qt::red);
QCOMPARE(spy1.count(), 12);
@@ -1507,6 +1548,89 @@ void tst_Q3DSSurfaceViewer::testDataInput()
delete slideInput;
}
+void tst_Q3DSSurfaceViewer::testTextureQuery_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testTextureQuery()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, DATAINPUT);
+ else
+ createOffscreenAndViewer(m_viewer, DATAINPUT);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QGuiApplication::processEvents();
+ // Test texture info getters, first for layer then for individual material.
+ // Texture id's are likely to change if test ordering changes.
+ QSize texsize;
+ GLenum format;
+
+ uint textureid = m_viewer->presentation()->textureId("Scene.Layer", texsize, format);
+ if (isWindow)
+ QCOMPARE(textureid, 6);
+ else
+ QCOMPARE(textureid, 7);
+
+ QCOMPARE(texsize, QSize(300,200));
+ QCOMPARE(format, GL_RGBA8);
+
+ textureid = m_viewer->presentation()->textureId("Scene.Layer.Rectangle.Default.diffusemap",
+ texsize, format);
+ if (isWindow)
+ QCOMPARE(textureid, 1);
+ else
+ QCOMPARE(textureid, 2);
+ QCOMPARE(texsize, QSize(400,200));
+ QCOMPARE(format, GL_RGBA8);
+
+ m_viewer->presentation()->setAttribute("Scene.Layer.Rectangle.Default.diffusemap",
+ "subpresentation", "");
+ m_viewer->presentation()->setAttribute("Scene.Layer.Rectangle.Default.diffusemap", "sourcepath",
+ "maps/OpenfootageNET_garage-512.hdr");
+
+ QGuiApplication::processEvents();
+
+ // Changed to HDR texture, studio-internally RGB8E but texture query should map to GL RGBA8
+ textureid = m_viewer->presentation()->textureId("Scene.Layer.Rectangle.Default.diffusemap",
+ texsize, format);
+ if (isWindow)
+ QCOMPARE(textureid, 8);
+ else
+ QCOMPARE(textureid, 9);
+
+ QCOMPARE(texsize, QSize(512,256));
+ QCOMPARE(format, GL_RGBA8);
+
+ // Reset textureid and format
+ textureid = m_viewer->presentation()->textureId("Scene.Layer", texsize, format);
+ if (isWindow)
+ QCOMPARE(textureid, 6);
+ else
+ QCOMPARE(textureid, 7);
+
+ // Test setting sourcepath without the file extension.
+ // Loading should succeed finding the .hdr file.
+ m_viewer->presentation()->setAttribute("Scene.Layer.Rectangle.Default.diffusemap", "sourcepath",
+ "maps/OpenfootageNET_garage-512");
+
+ QGuiApplication::processEvents();
+
+ // Changed to HDR texture, studio-internally RGB8E but texture query should map to GL RGBA8
+ textureid = m_viewer->presentation()->textureId("Scene.Layer.Rectangle.Default.diffusemap",
+ texsize, format);
+ if (isWindow)
+ QCOMPARE(textureid, 8);
+ else
+ QCOMPARE(textureid, 9);
+
+ QCOMPARE(texsize, QSize(512,256));
+ QCOMPARE(format, GL_RGBA8);
+}
QTEST_MAIN(tst_Q3DSSurfaceViewer)
diff --git a/tests/auto/studio3d/shared/maps/OpenfootageNET_garage-512.hdr b/tests/auto/studio3d/shared/maps/OpenfootageNET_garage-512.hdr
new file mode 100644
index 0000000..015b478
--- /dev/null
+++ b/tests/auto/studio3d/shared/maps/OpenfootageNET_garage-512.hdr
Binary files differ
diff --git a/tests/auto/studio3d/shared/presentation/activateactions.uip b/tests/auto/studio3d/shared/presentation/activateactions.uip
new file mode 100644
index 0000000..9adea68
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/activateactions.uip
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="7" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" preferKtx="False" flipCompressedTextures="False" >
+ <CustomColors count="16" >#969696 #780000 #ff0055 #ffffff #0a0a0a #ffffff #a0a8b2 #ffffff #ff643a #ffffff #4694ff #ffffff #ff0800 #ffffff #280000 #ffffff</CustomColors>
+ </ProjectSettings>
+ <Graph >
+ <Scene id="Scene_u31923" backgroundcolor="1 0 0 1" bgcolorenable="False" >
+ <Layer id="Layer_u40191" variants="" >
+ <Camera id="Camera_u60961" />
+ <Light id="Light_u46987" />
+ <Model id="Cube_u48840" variants="" >
+ <ReferencedMaterial id="Default_u50569" name="Default" />
+ </Model>
+ <Signal id="Signal_u2451" />
+ <Signal id="Signal2_u7200" />
+ </Layer>
+ <Material id="__Container_u55481" >
+ <Material id="materials//Default_u19189" />
+ </Material>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene_u31923" >
+ <Add ref="#Layer_u40191" />
+ <Add ref="#Camera_u60961" />
+ <Add ref="#Light_u46987" />
+ <Add ref="#__Container_u55481" name="__Container" />
+ <Add ref="#materials//Default_u19189" name="materials//Default" />
+ <State id="Scene-Slide1_u54514" name="Slide1" >
+ <Add ref="#Cube_u48840" name="Cube" rotation="20 360 20" sourcepath="#Cube" />
+ <Add ref="#Default_u50569" name="Default" referencedmaterial="#materials//Default_u19189" sourcepath="/Default" />
+ <Add ref="#Signal_u2451" name="Signal" endtime="3000" starttime="1000" >
+ <Action id="Signal-Action_u49670" eyeball="True" triggerObject="#Signal_u2451" event="onActivate" targetObject="#Scene_u31923" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="bgcolorenable" />
+ <HandlerArgument name="Property Value" type="Bool" argtype="Dependent" value="True" />
+ </Action>
+ <Action id="Signal-Action_u39742" eyeball="True" triggerObject="#Signal_u2451" event="onDeactivate" targetObject="#Scene_u31923" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="bgcolorenable" />
+ <HandlerArgument name="Property Value" type="Bool" argtype="Dependent" />
+ </Action>
+ </Add>
+ <Add ref="#Signal2_u7200" name="Signal2" endtime="3000" starttime="1000" >
+ <Action id="Signal2-Action_u44837" eyeball="True" triggerObject="#Signal2_u7200" event="onActivate" targetObject="#Signal2_u7200" handler="Emit Signal" >
+ <HandlerArgument name="Signal Name" type="String" argtype="Signal" value="mySignal1" />
+ </Action>
+ <Action id="Signal2-Action_u65378" eyeball="True" triggerObject="#Signal2_u7200" event="onDeactivate" targetObject="#Signal2_u7200" handler="Emit Signal" >
+ <HandlerArgument name="Signal Name" type="String" argtype="Signal" value="mySignal2" />
+ </Action>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/shared_presentations.h b/tests/auto/studio3d/shared/shared_presentations.h
index 6d38273..af9bd87 100644
--- a/tests/auto/studio3d/shared/shared_presentations.h
+++ b/tests/auto/studio3d/shared/shared_presentations.h
@@ -37,3 +37,4 @@ const QUrl SETTINGS = QUrl(QStringLiteral("qrc:/settings.uip"));
const QUrl MULTISLIDE = QUrl(QStringLiteral("qrc:/multislide.uip"));
const QUrl MOUSE = QUrl(QStringLiteral("qrc:/mouse.uip"));
const QUrl DATAINPUT = QUrl(QStringLiteral("qrc:/datainput.uia"));
+const QUrl ACTIVATEACTIONS = QUrl(QStringLiteral("qrc:/activateactions.uip"));
diff --git a/tests/auto/studio3d/shared/shared_presentations.qrc b/tests/auto/studio3d/shared/shared_presentations.qrc
index d4bb668..c55f2bc 100644
--- a/tests/auto/studio3d/shared/shared_presentations.qrc
+++ b/tests/auto/studio3d/shared/shared_presentations.qrc
@@ -11,5 +11,7 @@
<file alias="datainput.uip">presentation/datainput.uip</file>
<file alias="datainput.uia">presentation/datainput.uia</file>
<file alias="datainput_sub.uip">presentation/datainput_sub.uip</file>
+ <file>maps/OpenfootageNET_garage-512.hdr</file>
+ <file alias="activateactions.uip">presentation/activateactions.uip</file>
</qresource>
</RCC>
diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp
index 2273f89..084d8ae 100644
--- a/tests/auto/viewer/tst_qt3dsviewer.cpp
+++ b/tests/auto/viewer/tst_qt3dsviewer.cpp
@@ -105,7 +105,7 @@ void tst_qt3dsviewer::cleanup()
{
deleteCreated();
if (!m_ignoreError)
- QCOMPARE(m_studio3DItem->property("error").toString(), {});
+ QCOMPARE(m_studio3DItem->property("error").toString(), QString());
m_studio3DItem = nullptr;
m_viewer->hide();
m_viewer->deleteLater();
diff --git a/tools/viewer/main.cpp b/tools/viewer/main.cpp
index 1bcbe9d..4f39817 100644
--- a/tools/viewer/main.cpp
+++ b/tools/viewer/main.cpp
@@ -220,6 +220,9 @@ int main(int argc, char *argv[])
"The default value is 0.4"),
QCoreApplication::translate("main", "separation"),
QString::number(0.4)});
+ parser.addOption({"enableprogressivestereo",
+ QCoreApplication::translate("main",
+ "Enables progressive stereoscopic rendering.\n")});
parser.addOption({"convert-shader-cache",
QCoreApplication::translate("main",
"Convert base64 dump to shader cache file."),
@@ -391,6 +394,8 @@ int main(int argc, char *argv[])
if (ok)
appWindow->setProperty("stereoEyeSeparation", separation);
}
+ if (parser.isSet(QStringLiteral("enableprogressivestereo")))
+ appWindow->setProperty("stereoProgressiveEnabled", true);
viewer.setVariantList(variantList);
diff --git a/tools/viewer/qml/main.qml b/tools/viewer/qml/main.qml
index 153753a..93d52a8 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.5
+import QtStudio3D.OpenGL 2.8
import QtQuick.Window 2.2
ApplicationWindow {
@@ -52,6 +52,8 @@ ApplicationWindow {
property int scaleMode: ViewerSettings.ScaleModeCenter
property int stereoMode: ViewerSettings.StereoModeMono
property double stereoEyeSeparation: 0.4
+ property double stereoEyeRotation: 0.0
+ property bool stereoProgressiveEnabled: false
function closeMenus() {
fileMenu.close();
@@ -219,6 +221,8 @@ ApplicationWindow {
scaleMode: window.scaleMode
stereoMode: window.stereoMode
stereoEyeSeparation: window.stereoEyeSeparation
+ stereoEyeRotation: window.stereoEyeRotation
+ stereoProgressiveEnabled: window.stereoProgressiveEnabled
}
// Hider item keeps the Studio3D hidden until it starts running and we reset the
@@ -634,6 +638,17 @@ ApplicationWindow {
}
}
StyledMenuItem {
+ id: stereoProgressiveEnabled
+ text: qsTr("Progressive Rendering")
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ showCheckMark: window.stereoProgressiveEnabled
+ shortcut: "Ctrl+Shift+P"
+ onTriggered: {
+ if (enabled)
+ window.stereoProgressiveEnabled = !window.stereoProgressiveEnabled;
+ }
+ }
+ StyledMenuItem {
id: stereoEyeSeparationUp
text: qsTr("Increase Separation")
shortcut: "Ctrl+Shift++"
@@ -655,6 +670,32 @@ ApplicationWindow {
}
}
}
+ StyledMenuItem {
+ id: stereoEyeRotationUp
+ text: qsTr("Increase Rotation")
+ shortcut: "Ctrl+Shift+9"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ // Rotate in 0.1-degree steps
+ let step = Math.PI / 1800;
+ if (enabled)
+ window.stereoEyeRotation += step;
+ }
+ }
+ StyledMenuItem {
+ id: stereoEyeRotationDown
+ text: qsTr("Decrease Rotation")
+ shortcut: "Ctrl+Shift+8"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ // Rotate in 0.1-degree steps
+ let step = Math.PI / 1800;
+ window.stereoEyeRotation
+ = Math.max(0, window.stereoEyeRotation - step);
+ }
+ }
+ }
}
}
StyledMenuItem {
diff --git a/tools/viewer/viewer.pro b/tools/viewer/viewer.pro
index fc750b7..64f58ed 100644
--- a/tools/viewer/viewer.pro
+++ b/tools/viewer/viewer.pro
@@ -46,9 +46,11 @@ HEADERS += \
$$PWD/../../src/api/studio3d/q3dsdatainput.h
}
+!android {
LIBS += \
-lqt3dsopengl$$qtPlatformTargetSuffix() \
-lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+}
macos:QMAKE_RPATHDIR += @executable_path/../../../../lib
@@ -73,3 +75,14 @@ contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_PACKAGE_SOURCE_DIR = \
$$PWD/android
}
+
+android {
+ # qt prl files contain hard coded paths to android ndk so don't link against them
+ # If libraries are missing because of this they need to be added separately
+ CONFIG -= link_prl
+ LIBS += \
+ $$OUT_PWD/../../lib/libqt3dsopengl$$qtPlatformTargetSuffix().so \
+ $$OUT_PWD/../../lib/libqt3dsqmlstreamer$$qtPlatformTargetSuffix().so
+
+ QT += quick
+}