summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2018-06-07 14:30:27 +0200
committerLaszlo Agocs <laszlo.agocs@qt.io>2018-06-08 13:29:28 +0000
commitc935d5070888c2925701e5bacc8c905976d8e2df (patch)
treecab9f05b1a9b25a9aaf802eddff1f37deb17c734
parentd1669c623288a36f104d5d344b5799935e2857a4 (diff)
Generate custom material shadow map uniforms correctly
Send uNumShadowCubes, uNumShadowMaps, shadowMaps[], shadowCubes[] and set up shadowIdx correctly. Problem is, this won't actually fix the bug but at least we now generate the correct uniforms from our side. It also trades one FIXME for another one. Task-number: QT3DS-1840 Change-Id: I64ce5a841912f98616e558763a8360c8830741e5 Reviewed-by: Christian Stromme <christian.stromme@qt.io>
-rw-r--r--src/runtime/q3dsscenemanager.cpp101
-rw-r--r--src/runtime/q3dsscenemanager_p.h18
-rw-r--r--tests/scenes/shadows/materials/porcelain.material181
-rw-r--r--tests/scenes/shadows/shadow_on_custommaterial.uip63
-rw-r--r--tests/scenes/shadows/shadow_on_custommaterial_simplified.uip48
-rw-r--r--tests/scenes/shadows/shadow_on_custommaterial_simplified_one_light_only.uip42
-rw-r--r--tests/scenes/shadows/shadows_nonshadowlights_mixed.uip43
-rw-r--r--tests/scenes/shadows/shadows_nonshadowlights_mixed_custommaterial.uip46
8 files changed, 521 insertions, 21 deletions
diff --git a/src/runtime/q3dsscenemanager.cpp b/src/runtime/q3dsscenemanager.cpp
index 4324acf..11cf834 100644
--- a/src/runtime/q3dsscenemanager.cpp
+++ b/src/runtime/q3dsscenemanager.cpp
@@ -2203,7 +2203,10 @@ static const QVector3D qt3ds_shadowCube_dir[6] = {
QVector3D(0, 0, -1)
};
-void Q3DSSceneManager::updateCubeShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr)
+void Q3DSSceneManager::updateCubeShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d,
+ Q3DSLightNode *light3DS,
+ const QString &lightIndexStr,
+ int casterIdx)
{
Q_ASSERT(light3DS->lightType() != Q3DSLightNode::Directional);
Q3DSLightAttached *lightData = static_cast<Q3DSLightAttached *>(light3DS->attached());
@@ -2225,6 +2228,10 @@ void Q3DSSceneManager::updateCubeShadowMapParams(Q3DSLayerAttached::PerLightShad
d->shadowCamPropsParam->setName(QLatin1String("camera_properties"));
d->shadowCamPropsParam->setValue(QVector2D(light3DS->shadowFilter(), light3DS->shadowMapFar()));
+
+ d->materialParams.custMatShadowSamplerIdx = casterIdx; // will end up in shadowIdx
+ d->materialParams.custMatShadowSampler->setName(QLatin1String("shadowCubes[") + QString::number(casterIdx) + QLatin1String("]"));
+ d->materialParams.custMatShadowSampler->setValue(QVariant::fromValue(d->shadowMapTexture));
}
void Q3DSSceneManager::updateCubeShadowCam(Q3DSLayerAttached::PerLightShadowMapData *d, int faceIdx, Q3DSLightNode *light3DS)
@@ -2283,7 +2290,10 @@ void Q3DSSceneManager::genCubeBlurPassFg(Q3DSLayerAttached::PerLightShadowMapDat
filter->addParameter(d->shadowCamPropsParam);
}
-void Q3DSSceneManager::updateOrthoShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr)
+void Q3DSSceneManager::updateOrthoShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d,
+ Q3DSLightNode *light3DS,
+ const QString &lightIndexStr,
+ int casterIdx)
{
Q_ASSERT(light3DS->lightType() == Q3DSLightNode::Directional);
@@ -2304,6 +2314,10 @@ void Q3DSSceneManager::updateOrthoShadowMapParams(Q3DSLayerAttached::PerLightSha
d->shadowCamPropsParam->setName(QLatin1String("camera_properties"));
d->shadowCamPropsParam->setValue(QVector2D(light3DS->shadowFilter(), light3DS->shadowMapFar()));
+
+ d->materialParams.custMatShadowSamplerIdx = casterIdx; // will end up in shadowIdx
+ d->materialParams.custMatShadowSampler->setName(QLatin1String("shadowMaps[") + QString::number(casterIdx) + QLatin1String("]"));
+ d->materialParams.custMatShadowSampler->setValue(QVariant::fromValue(d->shadowMapTexture));
}
void Q3DSSceneManager::updateOrthoShadowCam(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, Q3DSLayerAttached *layerData)
@@ -2453,6 +2467,8 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
Q_ASSERT(layerData);
const int oldShadowCasterCount = layerData->shadowMapData.shadowCasters.count();
int lightIdx = 0;
+ int orthoCasterIdx = 0;
+ int cubeCasterIdx = 0;
for (Q3DSLayerAttached::PerLightShadowMapData &d : layerData->shadowMapData.shadowCasters)
d.active = false;
@@ -2460,7 +2476,12 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
// Go through the list of visible (eyeball==true) lights and pick the ones with castshadow==true.
for (Q3DSLightNode *light3DS : qAsConst(layerData->lightsData->lightNodes)) {
Q_ASSERT(light3DS->flags().testFlag(Q3DSNode::Active));
+ // Note the global indexing for shadow map uniforms too: a casting, a
+ // noncasting, and another shadow casting point light leads to uniforms
+ // like shadowcube1 and shadowcube3. (with the default material)
const QString lightIndexStr = QString::number(lightIdx++);
+ // On the other hand custom materials need a shadowIdx to index a
+ // shadowMaps or shadowCubes sampler uniform array. Hence ortho/cubeCasterIdx.
if (light3DS->castShadow()) {
auto it = std::find_if(layerData->shadowMapData.shadowCasters.begin(), layerData->shadowMapData.shadowCasters.end(),
@@ -2594,6 +2615,12 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
d->materialParams.shadowMatrixParam = new Qt3DRender::QParameter(layerData->entity);
if (!d->materialParams.shadowControlParam)
d->materialParams.shadowControlParam = new Qt3DRender::QParameter(layerData->entity);
+ if (!d->materialParams.custMatShadowSampler)
+ d->materialParams.custMatShadowSampler = new Qt3DRender::QParameter(layerData->entity);
+ if (!layerData->shadowMapData.custMatParams.numShadowCubesParam)
+ layerData->shadowMapData.custMatParams.numShadowCubesParam = new Qt3DRender::QParameter(layerData->entity);
+ if (!layerData->shadowMapData.custMatParams.numShadowMapsParam)
+ layerData->shadowMapData.custMatParams.numShadowMapsParam = new Qt3DRender::QParameter(layerData->entity);
// verify no globally used parameters get parented to this volatile framegraph subtree
Q_ASSERT(layerData->opaqueTag->parent());
@@ -2666,7 +2693,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
}
// set QParameter names and values
- updateCubeShadowMapParams(d, light3DS, lightIndexStr);
+ updateCubeShadowMapParams(d, light3DS, lightIndexStr, cubeCasterIdx);
} else {
Qt3DRender::QRenderTargetSelector *shadowRtSelector = new Qt3DRender::QRenderTargetSelector(d->subTreeRoot);
Qt3DRender::QRenderTarget *shadowRt = new Qt3DRender::QRenderTarget;
@@ -2718,7 +2745,7 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
genOrthoBlurPassFg(d, d->shadowMapTextureTemp, d->shadowMapTexture, QLatin1String("shadowOrthoBlurY"), light3DS);
// set QParameter names and values
- updateOrthoShadowMapParams(d, light3DS, lightIndexStr);
+ updateOrthoShadowMapParams(d, light3DS, lightIndexStr, orthoCasterIdx);
} // if isCube
} else {
// !needsFramegraph -> update the values that could have changed
@@ -2726,15 +2753,32 @@ void Q3DSSceneManager::updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDi
for (int faceIdx = 0; faceIdx < 6; ++faceIdx)
updateCubeShadowCam(d, faceIdx, light3DS);
- updateCubeShadowMapParams(d, light3DS, lightIndexStr);
+ updateCubeShadowMapParams(d, light3DS, lightIndexStr, cubeCasterIdx);
} else {
updateOrthoShadowCam(d, light3DS, layerData);
- updateOrthoShadowMapParams(d, light3DS, lightIndexStr);
+ updateOrthoShadowMapParams(d, light3DS, lightIndexStr, orthoCasterIdx);
}
}
+
+ if (isCube) {
+ light3DS->attached<Q3DSLightAttached>()->lightSource.shadowIdxParam->setValue(cubeCasterIdx);
+ ++cubeCasterIdx;
+ } else {
+ light3DS->attached<Q3DSLightAttached>()->lightSource.shadowIdxParam->setValue(orthoCasterIdx);
+ ++orthoCasterIdx;
+ }
} // if light3DS->castShadow
}
+ if (layerData->shadowMapData.custMatParams.numShadowCubesParam) {
+ layerData->shadowMapData.custMatParams.numShadowCubesParam->setName(QLatin1String("uNumShadowCubes"));
+ layerData->shadowMapData.custMatParams.numShadowCubesParam->setValue(cubeCasterIdx);
+ }
+ if (layerData->shadowMapData.custMatParams.numShadowMapsParam) {
+ layerData->shadowMapData.custMatParams.numShadowMapsParam->setName(QLatin1String("uNumShadowMaps"));
+ layerData->shadowMapData.custMatParams.numShadowMapsParam->setValue(orthoCasterIdx);
+ }
+
// Drop shadow map data for lights that are not casting anymore either due
// to a castshadow or eyeball property change.
for (int i = 0; i < layerData->shadowMapData.shadowCasters.count(); ++i) {
@@ -4209,13 +4253,17 @@ void Q3DSSceneManager::setLightProperties(Q3DSLightNode *light3DS, bool forceUpd
else
ls->heightParam->setValue(0.0f);
- // is this shadow stuff for lightmaps?
- const float shadowDist = 5000.0f; // camera->clipFar() ### FIXME later
+ // For custom materials. The default material does not use these as it
+ // generates the shader code dynamically and can therefore rely on uniforms
+ // named like shadowcube_<index> and shadowmap_<index>_control. Custom
+ // materials cannot do this and will instead use the shadow control and
+ // matrix from the lights array and use shadowIdx to index the array
+ // uniforms for the samplers.
if (!ls->shadowControlsParam) {
ls->shadowControlsParam = new Qt3DRender::QParameter;
ls->shadowControlsParam->setName(QLatin1String("shadowControls"));
}
- ls->shadowControlsParam->setValue(QVector4D(light3DS->shadowBias(), light3DS->shadowFactor(), shadowDist, 0));
+ ls->shadowControlsParam->setValue(QVector4D(light3DS->shadowBias(), light3DS->shadowFactor(), light3DS->shadowMapFar(), 0));
if (!ls->shadowViewParam) {
ls->shadowViewParam = new Qt3DRender::QParameter;
@@ -4229,8 +4277,8 @@ void Q3DSSceneManager::setLightProperties(Q3DSLightNode *light3DS, bool forceUpd
if (!ls->shadowIdxParam) {
ls->shadowIdxParam = new Qt3DRender::QParameter;
ls->shadowIdxParam->setName(QLatin1String("shadowIdx"));
+ ls->shadowIdxParam->setValue(0); // will get updated later in updateShadowMapStatus(), or stays 0 otherwise
}
- ls->shadowIdxParam->setValue(0); // ### FIXME later
}
Qt3DCore::QEntity *Q3DSSceneManager::buildModel(Q3DSModelNode *model3DS, Q3DSLayerNode *layer3DS, Qt3DCore::QEntity *parent)
@@ -4300,19 +4348,34 @@ Qt3DCore::QEntity *Q3DSSceneManager::buildModel(Q3DSModelNode *model3DS, Q3DSLay
return entity;
}
-static void addShadowSsaoParams(Q3DSLayerAttached *layerData, QVector<Qt3DRender::QParameter *> *params)
+static void addShadowSsaoParams(Q3DSLayerAttached *layerData, QVector<Qt3DRender::QParameter *> *params, bool isCustomMaterial)
{
for (const Q3DSLayerAttached::PerLightShadowMapData &sd : qAsConst(layerData->shadowMapData.shadowCasters)) {
- if (sd.materialParams.shadowSampler)
- params->append(sd.materialParams.shadowSampler);
- if (sd.materialParams.shadowMatrixParam)
- params->append(sd.materialParams.shadowMatrixParam);
- if (sd.materialParams.shadowControlParam)
- params->append(sd.materialParams.shadowControlParam);
+ if (isCustomMaterial) {
+ // ### FIXME QT3DS-1840 - enabling the following crashes on Intel
+#if 0
+ if (sd.materialParams.custMatShadowSampler)
+ params->append(sd.materialParams.custMatShadowSampler);
+#endif
+ } else {
+ if (sd.materialParams.shadowSampler)
+ params->append(sd.materialParams.shadowSampler);
+ if (sd.materialParams.shadowMatrixParam)
+ params->append(sd.materialParams.shadowMatrixParam);
+ if (sd.materialParams.shadowControlParam)
+ params->append(sd.materialParams.shadowControlParam);
+ }
}
if (layerData->ssaoTextureData.enabled && layerData->ssaoTextureData.ssaoTextureSampler)
params->append(layerData->ssaoTextureData.ssaoTextureSampler);
+
+ if (isCustomMaterial) {
+ if (layerData->shadowMapData.custMatParams.numShadowCubesParam)
+ params->append(layerData->shadowMapData.custMatParams.numShadowCubesParam);
+ if (layerData->shadowMapData.custMatParams.numShadowMapsParam)
+ params->append(layerData->shadowMapData.custMatParams.numShadowMapsParam);
+ }
}
void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
@@ -4404,7 +4467,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
}
}
- addShadowSsaoParams(layerData, &params);
+ addShadowSsaoParams(layerData, &params, false);
// Setup light probe parameters
if (defMatData->lightProbeOverrideTexture || modelData->layer3DS->lightProbe()) {
@@ -4484,7 +4547,7 @@ void Q3DSSceneManager::buildModelMaterial(Q3DSModelNode *model3DS)
}
}
- addShadowSsaoParams(layerData, &params);
+ addShadowSsaoParams(layerData, &params, true);
// Setup light probe parameters
if (custMatData->lightProbeOverrideTexture || modelData->layer3DS->lightProbe()) {
diff --git a/src/runtime/q3dsscenemanager_p.h b/src/runtime/q3dsscenemanager_p.h
index 4ba4d80..3584180 100644
--- a/src/runtime/q3dsscenemanager_p.h
+++ b/src/runtime/q3dsscenemanager_p.h
@@ -293,9 +293,18 @@ public:
Qt3DRender::QAbstractTexture *shadowDS = nullptr;
Qt3DRender::QParameter *cameraPositionParam = nullptr;
struct {
+ // the default material uses uniforms named like:
+ // shadowcube_<index> and shadowmap_<index>_matrix
Qt3DRender::QParameter *shadowSampler = nullptr;
Qt3DRender::QParameter *shadowMatrixParam = nullptr;
Qt3DRender::QParameter *shadowControlParam = nullptr;
+ // custom materials cannot do this, instead they use the shadow
+ // matrix and control vec from the lights array, plus:
+ // uniform sampler2D shadowMaps[MAX_NUM_SHADOWS];
+ // uniform samplerCube shadowCubes[MAX_NUM_SHADOWS];
+ // which are then indexed by shadowIdx.
+ int custMatShadowSamplerIdx = 0;
+ Qt3DRender::QParameter *custMatShadowSampler = nullptr;
} materialParams;
Qt3DRender::QParameter *shadowCamPropsParam = nullptr;
Qt3DRender::QCamera *shadowCamOrtho = nullptr;
@@ -305,6 +314,11 @@ public:
Qt3DRender::QFrameGraphNode *shadowRoot = nullptr;
QVector<PerLightShadowMapData> shadowCasters;
Qt3DRender::QAbstractTexture *defaultShadowDS = nullptr;
+ struct CustomMaterialData {
+ // custom materials need a uNumShadowMaps and uNumShadowCubes
+ Qt3DRender::QParameter *numShadowMapsParam = nullptr;
+ Qt3DRender::QParameter *numShadowCubesParam = nullptr;
+ } custMatParams;
} shadowMapData;
struct ProgAAData {
@@ -760,11 +774,11 @@ private:
void updateAoParameters(Q3DSLayerNode *layer3DS);
void updateSsaoStatus(Q3DSLayerNode *layer3DS, bool *aoDidChange = nullptr);
void updateShadowMapStatus(Q3DSLayerNode *layer3DS, bool *smDidChange = nullptr);
- void updateCubeShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr);
+ void updateCubeShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr, int casterIdx);
void updateCubeShadowCam(Q3DSLayerAttached::PerLightShadowMapData *d, int faceIdx, Q3DSLightNode *light3DS);
void genCubeBlurPassFg(Q3DSLayerAttached::PerLightShadowMapData *d, Qt3DRender::QAbstractTexture *inTex,
Qt3DRender::QAbstractTexture *outTex, const QString &passName, Q3DSLightNode *light3DS);
- void updateOrthoShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr);
+ void updateOrthoShadowMapParams(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, const QString &lightIndexStr, int casterIdx);
void updateOrthoShadowCam(Q3DSLayerAttached::PerLightShadowMapData *d, Q3DSLightNode *light3DS, Q3DSLayerAttached *layerData);
void genOrthoBlurPassFg(Q3DSLayerAttached::PerLightShadowMapData *d, Qt3DRender::QAbstractTexture *inTex,
Qt3DRender::QAbstractTexture *outTex, const QString &passName, Q3DSLightNode *light3DS);
diff --git a/tests/scenes/shadows/materials/porcelain.material b/tests/scenes/shadows/materials/porcelain.material
new file mode 100644
index 0000000..b21cda7
--- /dev/null
+++ b/tests/scenes/shadows/materials/porcelain.material
@@ -0,0 +1,181 @@
+<Material name="porcelain" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" description="Environment texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" description="Enable environment mapping" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" description="Baked shadow texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Shadow Mapping" name="uShadowMappingEnabled" description="Enable shadow mapping" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Index of Refraction" name="material_ior" type="Float" default="1.500000" description="Index of refraction of the material" category="Material"/>
+ <Property formalName="Glossiness" name="glossy_weight" type="Float" min="0.000000" max="1.000000" default="1.000000" description="Strength of glossy reflection" category="Material"/>
+ <Property formalName="Roughness" name="roughness" type="Float" min="0.000000" max="1.000000" default="0.150000" description="Roughness of the material.\n0 = fully specular\n1 = fully diffuse" category="Material"/>
+ <Property formalName="Porcelain Color" name="porcelain_color" type="Color" default="0.92 0.92 0.92" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define QT3DS_ENABLE_UV0 1
+#define QT3DS_ENABLE_WORLD_POSITION 1
+#define QT3DS_ENABLE_TEXTAN 1
+#define QT3DS_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "diffuseReflectionBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+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].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * lightDiffuse * sampleAreaDiffuse( layers[0].tanFrame, varWorldPos, lightIdx );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * diffuseReflectionBSDFEnvironment( normal, 0.000000 ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * sampleDiffuse( layers[0].tanFrame ) * aoFactor;
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( 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 += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0 : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( material_ior ), glossy_weight, vec4( vec3( 1, 1, 1 ), 1.0).rgb, layers[0].layer, layers[0].base * vec4( porcelain_color, 1.0), alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="5"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/tests/scenes/shadows/shadow_on_custommaterial.uip b/tests/scenes/shadows/shadow_on_custommaterial.uip
new file mode 100644
index 0000000..d290e69
--- /dev/null
+++ b/tests/scenes/shadows/shadow_on_custommaterial.uip
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="4" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="1080" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="porcelain" name="porcelain" sourcepath="materials/porcelain.material" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <CustomMaterial id="Default" class="#porcelain" />
+ </Model>
+ <Model id="Cube" >
+ <CustomMaterial id="Default_001" class="#porcelain" />
+ </Model>
+ <Light id="Light2" />
+ <Model id="Cube2" >
+ <Material id="Default_002" name="Default" />
+ </Model>
+ <Model id="Cone" >
+ <Material id="Default_003" name="Default" />
+ </Model>
+ <Model id="Sphere" >
+ <Material id="Default_004" name="Default" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" position="0 300 -600" rotation="20 0 0" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Light" name="Light" brightness="100" castshadow="True" lightambient="0 0 0" lightdiffuse="0.666667 0 0" lightspecular="0.666667 0 0" lighttype="Point" position="0 203.135 0" rotation="0 0 0" shdwbias="0.001" shdwfactor="100" shdwfilter="1" shdwmapres="11" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 0 100 100 10 134.027 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 203.135 100 100 10 332.749 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Rectangle" name="Rectangle" rotation="90 0 0" scale="10 10 1" sourcepath="#Rectangle" />
+ <Add ref="#Default" name="Default" />
+ <Add ref="#Cube" name="Cube" position="-203.905 48.1771 0" sourcepath="#Cube" />
+ <Add ref="#Default_001" name="Default" />
+ <Add ref="#Light2" name="Light2" brightness="100" castshadow="True" lightdiffuse="0 0.666667 0" lightspecular="0 0.666667 0" lighttype="Point" position="0 219.345 0" rotation="0 0 0" shdwbias="0.001" shdwfactor="100" shdwfilter="1" shdwmapres="11" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -195.913 100 100 10 236.863 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 219.345 100 100 10 219.345 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 -319.932 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Cube2" name="Cube2" position="191.482 50.5886 0" sourcepath="#Cube" />
+ <Add ref="#Default_002" />
+ <Add ref="#Cone" name="Cone" position="0 0 -274.247" sourcepath="#Cone" />
+ <Add ref="#Default_003" />
+ <Add ref="#Sphere" name="Sphere" position="0 49.2835 288.235" sourcepath="#Sphere" />
+ <Add ref="#Default_004" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/shadows/shadow_on_custommaterial_simplified.uip b/tests/scenes/shadows/shadow_on_custommaterial_simplified.uip
new file mode 100644
index 0000000..821b13a
--- /dev/null
+++ b/tests/scenes/shadows/shadow_on_custommaterial_simplified.uip
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="4" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="1080" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="porcelain" name="porcelain" sourcepath="materials/porcelain.material" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <CustomMaterial id="Default" class="#porcelain" />
+ </Model>
+ <Light id="Light2" />
+ <Model id="Cube2" >
+ <Material id="Default_002" name="Default" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" position="0 300 -600" rotation="20 0 0" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Light" name="Light" brightness="100" castshadow="True" lightambient="0 0 0" lightdiffuse="0.666667 0 0" lightspecular="0.666667 0 0" lighttype="Point" position="0 203.135 0" rotation="0 0 0" shdwbias="0.001" shdwfactor="100" shdwfilter="1" shdwmapres="11" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 0 100 100 10 134.027 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 203.135 100 100 10 332.749 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Rectangle" name="Rectangle" rotation="90 0 0" scale="10 10 1" sourcepath="#Rectangle" />
+ <Add ref="#Default" name="Default" />
+ <Add ref="#Light2" name="Light2" brightness="100" castshadow="True" lightdiffuse="0 0.666667 0" lightspecular="0 0.666667 0" lighttype="Point" position="0 219.345 0" rotation="0 0 0" shdwbias="0.001" shdwfactor="100" shdwfilter="1" shdwmapres="11" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -195.913 100 100 10 236.863 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 219.345 100 100 10 219.345 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 -319.932 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Cube2" name="Cube2" position="191.482 50.5886 0" sourcepath="#Cube" />
+ <Add ref="#Default_002" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/shadows/shadow_on_custommaterial_simplified_one_light_only.uip b/tests/scenes/shadows/shadow_on_custommaterial_simplified_one_light_only.uip
new file mode 100644
index 0000000..2f712eb
--- /dev/null
+++ b/tests/scenes/shadows/shadow_on_custommaterial_simplified_one_light_only.uip
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="4" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="1080" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="porcelain" name="porcelain" sourcepath="materials/porcelain.material" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <CustomMaterial id="Default" class="#porcelain" />
+ </Model>
+ <Model id="Cube2" >
+ <Material id="Default_002" name="Default" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" position="0 300 -600" rotation="20 0 0" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Light" name="Light" brightness="100" castshadow="True" lightambient="0 0 0" lightdiffuse="0.666667 0 0" lightspecular="0.666667 0 0" lighttype="Point" position="0 203.135 0" rotation="0 0 0" shdwbias="0.001" shdwfactor="100" shdwfilter="1" shdwmapres="11" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 0 100 100 10 134.027 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 203.135 100 100 10 332.749 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Rectangle" name="Rectangle" rotation="90 0 0" scale="10 10 1" sourcepath="#Rectangle" />
+ <Add ref="#Default" name="Default" />
+ <Add ref="#Cube2" name="Cube2" position="191.482 50.5886 0" sourcepath="#Cube" />
+ <Add ref="#Default_002" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/shadows/shadows_nonshadowlights_mixed.uip b/tests/scenes/shadows/shadows_nonshadowlights_mixed.uip
new file mode 100644
index 0000000..d4b2362
--- /dev/null
+++ b/tests/scenes/shadows/shadows_nonshadowlights_mixed.uip
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="4" >
+ <Project >
+ <ProjectSettings author="" company="Eagle Jump" presentationWidth="800" presentationHeight="480" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Cylinder" >
+ <Material id="Material_001" />
+ </Model>
+ <Light id="shadowcaster" />
+ <Light id="noncaster" />
+ <Light id="shadowcaster2" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Rectangle" name="Rectangle" position="-5.77344 -34.641 0" rotation="53.5 0 0" scale="6.30691 5.36799 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" />
+ <Add ref="#Cylinder" name="Cylinder" position="26.809 49.9481 25.2529" rotation="-52.8354 30.8347 -4.94139" scale="1.16992 0.986966 1" sourcepath="#Cylinder" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 -52.8354 100 100 10 50 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 30.8347 100 100 10 30.8347 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 -4.94139 100 100 10 -4.94139 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0.501961 1 0.501961" />
+ <Add ref="#shadowcaster" name="shadowcaster" castshadow="True" lightdiffuse="1 0.662745 0.501961" lighttype="Point" position="392.861 235.972 3.46274" shdwbias="0" shdwfactor="31.9375" shdwfilter="27.8125" shdwmapfar="5000" shdwmapres="9" />
+ <Add ref="#noncaster" name="noncaster" lighttype="Point" position="294.449 -51.9615 0" />
+ <Add ref="#shadowcaster2" name="shadowcaster2" castshadow="True" lighttype="Point" position="511.618 70.4722 0" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/shadows/shadows_nonshadowlights_mixed_custommaterial.uip b/tests/scenes/shadows/shadows_nonshadowlights_mixed_custommaterial.uip
new file mode 100644
index 0000000..e1f9452
--- /dev/null
+++ b/tests/scenes/shadows/shadows_nonshadowlights_mixed_custommaterial.uip
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="4" >
+ <Project >
+ <ProjectSettings author="" company="Eagle Jump" presentationWidth="800" presentationHeight="480" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="porcelain" name="porcelain" sourcepath="materials/porcelain.material" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Model id="Rectangle" >
+ <CustomMaterial id="Material" class="#porcelain" />
+ </Model>
+ <Model id="Cylinder" >
+ <Material id="Material_001" />
+ </Model>
+ <Light id="shadowcaster" />
+ <Light id="noncaster" />
+ <Light id="shadowcaster2" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Rectangle" name="RectangleWithCustomMaterial" position="-5.77344 -34.641 0" rotation="53.5 0 0" scale="6.30691 5.36799 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" name="Material" />
+ <Add ref="#Cylinder" name="Cylinder" position="26.809 49.9481 25.2529" rotation="-52.8354 30.8347 -4.94139" scale="1.16992 0.986966 1" sourcepath="#Cylinder" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 -52.8354 100 100 10 50 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 30.8347 100 100 10 30.8347 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 -4.94139 100 100 10 -4.94139 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0.501961 1 0.501961" />
+ <Add ref="#shadowcaster" name="shadowcaster" castshadow="True" lightdiffuse="1 0.662745 0.501961" lighttype="Point" position="392.861 235.972 3.46274" shdwbias="0" shdwfactor="31.9375" shdwfilter="27.8125" shdwmapfar="5000" shdwmapres="9" />
+ <Add ref="#noncaster" name="noncaster" lighttype="Point" position="294.449 -51.9615 0" />
+ <Add ref="#shadowcaster2" name="shadowcaster2" castshadow="True" lighttype="Point" position="511.618 70.4722 0" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>