summaryrefslogtreecommitdiffstats
path: root/res/effectlib
diff options
context:
space:
mode:
Diffstat (limited to 'res/effectlib')
-rw-r--r--res/effectlib/Fxaa3_11.glsllib2073
-rw-r--r--res/effectlib/Fxaa3_8.glsllib1423
-rw-r--r--res/effectlib/SMAA.glsllib1444
-rw-r--r--res/effectlib/SSAOCustomMaterial.glsllib91
-rw-r--r--res/effectlib/abbeNumberIOR.glsllib36
-rw-r--r--res/effectlib/anisotropyConversion.glsllib46
-rw-r--r--res/effectlib/average.glsllib35
-rw-r--r--res/effectlib/blendColorLayers.glsllib45
-rw-r--r--res/effectlib/blur.glsllib295
-rw-r--r--res/effectlib/calculateRoughness.glsllib63
-rw-r--r--res/effectlib/coordinateSource.glsllib55
-rw-r--r--res/effectlib/cube.glsllib50
-rw-r--r--res/effectlib/customCurveLayer.glsllib42
-rw-r--r--res/effectlib/customMaterial.glsllib47
-rw-r--r--res/effectlib/customMaterialFragBody.glsllib84
-rw-r--r--res/effectlib/customMaterialFragBodyAO.glsllib90
-rw-r--r--res/effectlib/defaultMaterialBumpNoLod.glsllib52
-rw-r--r--res/effectlib/defaultMaterialFileBumpTexture.glsllib40
-rw-r--r--res/effectlib/defaultMaterialFileDisplacementTexture.glsllib40
-rw-r--r--res/effectlib/defaultMaterialFileNormalTexture.glsllib40
-rw-r--r--res/effectlib/defaultMaterialFresnel.glsllib44
-rw-r--r--res/effectlib/defaultMaterialLighting.glsllib80
-rw-r--r--res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib43
-rw-r--r--res/effectlib/depthpass.glsllib80
-rw-r--r--res/effectlib/dfTint.glsllib35
-rw-r--r--res/effectlib/diffuseReflectionBSDF.glsllib66
-rw-r--r--res/effectlib/diffuseTransmissionBSDF.glsllib42
-rw-r--r--res/effectlib/directionalFactor.glsllib42
-rw-r--r--res/effectlib/distancefieldtext.frag28
-rw-r--r--res/effectlib/distancefieldtext.vert77
-rw-r--r--res/effectlib/distancefieldtext_core.frag11
-rw-r--r--res/effectlib/distancefieldtext_core.vert15
-rw-r--r--res/effectlib/distancefieldtext_dropshadow.frag47
-rw-r--r--res/effectlib/distancefieldtext_dropshadow.vert88
-rw-r--r--res/effectlib/distancefieldtext_dropshadow_core.frag28
-rw-r--r--res/effectlib/distancefieldtext_dropshadow_core.vert25
-rw-r--r--res/effectlib/effect.glsllib148
-rw-r--r--res/effectlib/evalBakedShadowMap.glsllib36
-rw-r--r--res/effectlib/evalEnvironmentMap.glsllib55
-rw-r--r--res/effectlib/evalLightmaps.glsllib56
-rw-r--r--res/effectlib/fileBumpTexture.glsllib119
-rw-r--r--res/effectlib/fileDisplacementTexture.glsllib71
-rw-r--r--res/effectlib/fileTexture.glsllib48
-rw-r--r--res/effectlib/flakeNoiseBumpTexture.glsllib46
-rw-r--r--res/effectlib/flakeNoiseTexture.glsllib66
-rw-r--r--res/effectlib/fresnelLayer.glsllib109
-rw-r--r--res/effectlib/funcareaLightVars.glsllib32
-rw-r--r--res/effectlib/funccalculateDiffuseAreaOld.glsllib29
-rw-r--r--res/effectlib/funccalculatePointLightAttenuation.glsllib4
-rw-r--r--res/effectlib/funccomputeMicroHit.glsllib50
-rw-r--r--res/effectlib/funcdiffuseReflectionBSDF.glsllib43
-rw-r--r--res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib5
-rw-r--r--res/effectlib/funcgetTransformedUVCoords.glsllib4
-rw-r--r--res/effectlib/funcsampleAreaGlossyDefault.glsllib42
-rw-r--r--res/effectlib/funcsampleLightVars.glsllib29
-rw-r--r--res/effectlib/funcspecularBSDF.glsllib42
-rw-r--r--res/effectlib/gles2/SSAOCustomMaterial.glsllib100
-rw-r--r--res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib52
-rw-r--r--res/effectlib/gles2/evalEnvironmentMap.glsllib37
-rw-r--r--res/effectlib/gles2/funcareaLightVars.glsllib29
-rw-r--r--res/effectlib/gles2/funcsampleLightVars.glsllib27
-rw-r--r--res/effectlib/gles2/microfacetBSDF.glsllib233
-rw-r--r--res/effectlib/gles2/monoChannel.glsllib58
-rw-r--r--res/effectlib/gles2/refraction.glsllib87
-rw-r--r--res/effectlib/gles2/sampleProbe.glsllib482
-rw-r--r--res/effectlib/gles2/shadowMapping.glsllib106
-rw-r--r--res/effectlib/gles2/tangentSpaceNormalTexture.glsllib97
-rw-r--r--res/effectlib/gradient3Recolor.glsllib73
-rw-r--r--res/effectlib/gradient3Texture.glsllib36
-rw-r--r--res/effectlib/gradientGetPosition.glsllib76
-rw-r--r--res/effectlib/luminance.glsllib62
-rw-r--r--res/effectlib/miNoise.glsllib113
-rw-r--r--res/effectlib/microfacetBSDF.glsllib259
-rw-r--r--res/effectlib/monoChannel.glsllib58
-rw-r--r--res/effectlib/normalizedMix.glsllib42
-rw-r--r--res/effectlib/perlinNoise.glsllib234
-rw-r--r--res/effectlib/perlinNoiseBumpTexture.glsllib49
-rw-r--r--res/effectlib/perlinNoiseTexture.glsllib11
-rw-r--r--res/effectlib/physGlossyBSDF.glsllib159
-rw-r--r--res/effectlib/random255.glsllib56
-rw-r--r--res/effectlib/refraction.glsllib87
-rw-r--r--res/effectlib/rotationTranslationScale.glsllib50
-rw-r--r--res/effectlib/sampleArea.glsllib180
-rw-r--r--res/effectlib/sampleLight.glsllib130
-rw-r--r--res/effectlib/sampleProbe.glsllib473
-rw-r--r--res/effectlib/screenSpaceAO.glsllib150
-rw-r--r--res/effectlib/screenSpaceDO.glsllib158
-rw-r--r--res/effectlib/shadowMapping.glsllib106
-rw-r--r--res/effectlib/shadowMappingFragment.glsllib10
-rw-r--r--res/effectlib/simpleGlossyBSDF.glsllib99
-rw-r--r--res/effectlib/specularBSDF.glsllib47
-rw-r--r--res/effectlib/spotEdf.glsllib42
-rw-r--r--res/effectlib/square.glsllib35
-rw-r--r--res/effectlib/tangentSpaceNormalTexture.glsllib91
-rw-r--r--res/effectlib/tessellationLinear.glsllib104
-rw-r--r--res/effectlib/tessellationLinearCM.glsllib174
-rw-r--r--res/effectlib/tessellationNPatch.glsllib290
-rw-r--r--res/effectlib/tessellationNPatchCM.glsllib194
-rw-r--r--res/effectlib/tessellationPath.glsllib183
-rw-r--r--res/effectlib/tessellationPhong.glsllib170
-rw-r--r--res/effectlib/tessellationPhongCM.glsllib179
-rw-r--r--res/effectlib/textureCoordinateInfo.glsllib54
-rw-r--r--res/effectlib/transformCoordinate.glsllib43
-rw-r--r--res/effectlib/vertexFragmentBase.glsllib61
-rw-r--r--res/effectlib/viewProperties.glsllib41
-rw-r--r--res/effectlib/weightedLayer.glsllib35
-rw-r--r--res/effectlib/wireframeCM.glsllib169
107 files changed, 13767 insertions, 0 deletions
diff --git a/res/effectlib/Fxaa3_11.glsllib b/res/effectlib/Fxaa3_11.glsllib
new file mode 100644
index 0000000..f5de208
--- /dev/null
+++ b/res/effectlib/Fxaa3_11.glsllib
@@ -0,0 +1,2073 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*============================================================================
+
+
+ NVIDIA FXAA 3.11 by TIMOTHY LOTTES
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source, setup defines for the desired configuration.
+When providing multiple shaders (for different presets),
+simply setup the defines differently in multiple files.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_5 1
+ #define FXAA_QUALITY__PRESET 12
+
+Or,
+
+ #define FXAA_360 1
+
+Or,
+
+ #define FXAA_PS3 1
+
+Etc.
+
+(2.)
+Then include this file,
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader.
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+As for FXAA 3.11 all inputs for all shaders are the same
+to enable easy porting between platforms.
+
+ return FxaaPixelShader(...);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL (see next section).
+Or use,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+(5.)
+Setup engine to provide the following constants
+which are used in the FxaaPixelShader() inputs,
+
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+
+Look at the FXAA Quality FxaaPixelShader() for docs on inputs.
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "fxaaConsolePosPos"
+such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+
+(7.)
+Insure the texture sampler(s) used by FXAA are set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input unless the following is set,
+
+ #define FXAA_GREEN_AS_LUMA 1
+
+In which case the engine uses green in place of luma,
+and requires RGB input is in a non-linear colorspace.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be non-linear,
+or linear when FXAA_GREEN_AS_LUMA is not set.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+
+If FXAA_GREEN_AS_LUMA is not set,
+luma must be stored in the alpha channel prior to running FXAA.
+This luma should be in a perceptual space (could be gamma 2.0).
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, FxaaFloat3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ BEING LINEARLY CORRECT?
+------------------------------------------------------------------------------
+Applying FXAA to a framebuffer with linear RGB color will look worse.
+This is very counter intuitive, but happends to be true in this case.
+The reason is because dithering artifacts will be more visiable
+in a linear colorspace.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+A. Or use FXAA_GREEN_AS_LUMA.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+// FXAA_360_OPT is a prototype for the new optimized 360 version.
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360_OPT
+ #define FXAA_360_OPT 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ // Likely better to just run FXAA_PC, and use a really low preset.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_GREEN_AS_LUMA
+ //
+ // For those using non-linear color,
+ // and either not able to get luma in alpha, or not wanting to,
+ // this enables FXAA to run using green as a proxy for luma.
+ // So with this enabled, no need to pack luma in alpha.
+ //
+ // This will turn off AA on anything which lacks some amount of green.
+ // Pure red and blue or combination of only R and B, will get no AA.
+ //
+ // Might want to lower the settings for both,
+ // fxaaConsoleEdgeThresholdMin
+ // fxaaQualityEdgeThresholdMin
+ // In order to insure AA does not get turned off on colors
+ // which contain a minor amount of green.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_GREEN_AS_LUMA 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this ON adds 2 cycles to the shader.
+ // On 360 turning this OFF adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ // Probably will not work when FXAA_GREEN_AS_LUMA = 1.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+
+#ifdef GL_ES
+ #if __VERSION__ >= 310
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#else
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+ #endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE PS3 - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE__PS3_EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges on PS3 only.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ // 2.0 is really soft (good for vector graphics inputs)
+ //
+ #if 1
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 8.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 4.0
+ #endif
+ #if 0
+ #define FXAA_CONSOLE__PS3_EDGE_SHARPNESS 2.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__PS3_EDGE_THRESHOLD
+ //
+ // Only effects PS3.
+ // Non-PS3 tuning is done with shader input.
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE__PS3_EDGE_THRESHOLD 0.25
+ #endif
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+------------------------------------------------------------------------------
+NOTE the other tuning knobs are now in the shader function inputs!
+============================================================================*/
+#ifndef FXAA_QUALITY__PRESET
+ //
+ // Choose the quality preset.
+ // This needs to be compiled into the shader as it effects code.
+ // Best option to include multiple presets is to
+ // in each shader define the preset, then include this file.
+ //
+ // OPTIONS
+ // -----------------------------------------------------------------------
+ // 10 to 15 - default medium dither (10=fastest, 15=highest quality)
+ // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality)
+ // 39 - no dither, very expensive
+ //
+ // NOTES
+ // -----------------------------------------------------------------------
+ // 12 = slightly faster then FXAA 3.9 and higher edge quality (default)
+ // 13 = about same speed as FXAA 3.9 and better than 12
+ // 23 = closest to FXAA 3.9 visually and performance wise
+ // _ = the lowest digit is directly related to performance
+ // _ = the highest digit is directly related to style
+ //
+ #define FXAA_QUALITY__PRESET 12
+#endif
+
+
+/*============================================================================
+
+ FXAA QUALITY - PRESETS
+
+============================================================================*/
+
+/*============================================================================
+ FXAA QUALITY - MEDIUM DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 10)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 3.0
+ #define FXAA_QUALITY__P2 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 11)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 3.0
+ #define FXAA_QUALITY__P3 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 12)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 4.0
+ #define FXAA_QUALITY__P4 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 13)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 4.0
+ #define FXAA_QUALITY__P5 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 14)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 4.0
+ #define FXAA_QUALITY__P6 12.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 15)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 12.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - LOW DITHER PRESETS
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 20)
+ #define FXAA_QUALITY__PS 3
+ #define FXAA_QUALITY__P0 1.5
+ #define FXAA_QUALITY__P1 2.0
+ #define FXAA_QUALITY__P2 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 21)
+ #define FXAA_QUALITY__PS 4
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 22)
+ #define FXAA_QUALITY__PS 5
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 23)
+ #define FXAA_QUALITY__PS 6
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 24)
+ #define FXAA_QUALITY__PS 7
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 3.0
+ #define FXAA_QUALITY__P6 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 25)
+ #define FXAA_QUALITY__PS 8
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 4.0
+ #define FXAA_QUALITY__P7 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 26)
+ #define FXAA_QUALITY__PS 9
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 4.0
+ #define FXAA_QUALITY__P8 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 27)
+ #define FXAA_QUALITY__PS 10
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 4.0
+ #define FXAA_QUALITY__P9 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 28)
+ #define FXAA_QUALITY__PS 11
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 4.0
+ #define FXAA_QUALITY__P10 8.0
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_QUALITY__PRESET == 29)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.5
+ #define FXAA_QUALITY__P2 2.0
+ #define FXAA_QUALITY__P3 2.0
+ #define FXAA_QUALITY__P4 2.0
+ #define FXAA_QUALITY__P5 2.0
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+/*============================================================================
+ FXAA QUALITY - EXTREME QUALITY
+============================================================================*/
+#if (FXAA_QUALITY__PRESET == 39)
+ #define FXAA_QUALITY__PS 12
+ #define FXAA_QUALITY__P0 1.0
+ #define FXAA_QUALITY__P1 1.0
+ #define FXAA_QUALITY__P2 1.0
+ #define FXAA_QUALITY__P3 1.0
+ #define FXAA_QUALITY__P4 1.0
+ #define FXAA_QUALITY__P5 1.5
+ #define FXAA_QUALITY__P6 2.0
+ #define FXAA_QUALITY__P7 2.0
+ #define FXAA_QUALITY__P8 2.0
+ #define FXAA_QUALITY__P9 2.0
+ #define FXAA_QUALITY__P10 4.0
+ #define FXAA_QUALITY__P11 8.0
+#endif
+
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1)
+ #define FxaaBool bool
+ #define FxaaDiscard discard
+ #define FxaaFloat float
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaHalf float
+ #define FxaaHalf2 vec2
+ #define FxaaHalf3 vec3
+ #define FxaaHalf4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaTex sampler2D
+#else
+ #define FxaaBool bool
+ #define FxaaDiscard clip(-1)
+ #define FxaaFloat float
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaHalf half
+ #define FxaaHalf2 half2
+ #define FxaaHalf3 half3
+ #define FxaaHalf4 half4
+ #define FxaaSat(x) saturate(x)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_120 == 1)
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_GLSL_130 == 1)
+ // Requires "#version 130" or better
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
+ #define FxaaTexGreen4(t, p) textureGather(t, p, 1)
+ #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1)
+ #define FxaaInt2 float2
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_4 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_5 == 1)
+ #define FxaaInt2 int2
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o) t.tex.GatherAlpha(t.smpl, p, o)
+ #define FxaaTexGreen4(t, p) t.tex.GatherGreen(t.smpl, p)
+ #define FxaaTexOffGreen4(t, p, o) t.tex.GatherGreen(t.smpl, p, o)
+#endif
+
+
+/*============================================================================
+ GREEN AS LUMA OPTION SUPPORT FUNCTION
+============================================================================*/
+#if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.w; }
+#else
+ FxaaFloat FxaaLuma(FxaaFloat4 rgba) { return rgba.y; }
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ //
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy} = center of pixel
+ FxaaFloat2 pos,
+ //
+ // Used only for FXAA Console, and not used on the 360 version.
+ // Use noperspective interpolation here (turn off perspective interpolation).
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ FxaaFloat4 fxaaConsolePosPos,
+ //
+ // Input color texture.
+ // {rgb_} = color in linear or perceptual color space
+ // if (FXAA_GREEN_AS_LUMA == 0)
+ // {___a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 2nd sampler.
+ // This sampler needs to have an exponent bias of -1.
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ //
+ // Only used on the optimized 360 version of FXAA Console.
+ // For everything but 360, just use the same input here as for "tex".
+ // For 360, same texture, just alias with a 3nd sampler.
+ // This sampler needs to have an exponent bias of -2.
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ //
+ // Only used on FXAA Quality.
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ FxaaFloat2 fxaaQualityRcpFrame,
+ //
+ // Only used on FXAA Console.
+ // This must be from a constant/uniform.
+ // This effects sub-pixel AA quality and inversely sharpness.
+ // Where N ranges between,
+ // N = 0.50 (default)
+ // N = 0.33 (sharper)
+ // {x___} = -N/screenWidthInPixels
+ // {_y__} = -N/screenHeightInPixels
+ // {__z_} = N/screenWidthInPixels
+ // {___w} = N/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ //
+ // Only used on FXAA Console.
+ // Not used on 360, but used on PS3 and PC.
+ // This must be from a constant/uniform.
+ // {x___} = -2.0/screenWidthInPixels
+ // {_y__} = -2.0/screenHeightInPixels
+ // {__z_} = 2.0/screenWidthInPixels
+ // {___w} = 2.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ //
+ // Only used on FXAA Console.
+ // Only used on 360 in place of fxaaConsoleRcpFrameOpt2.
+ // This must be from a constant/uniform.
+ // {x___} = 8.0/screenWidthInPixels
+ // {_y__} = 8.0/screenHeightInPixels
+ // {__z_} = -4.0/screenWidthInPixels
+ // {___w} = -4.0/screenHeightInPixels
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__SUBPIX define.
+ // It is here now to allow easier tuning.
+ // Choose the amount of sub-pixel aliasing removal.
+ // This can effect sharpness.
+ // 1.00 - upper limit (softer)
+ // 0.75 - default amount of filtering
+ // 0.50 - lower limit (sharper, less sub-pixel aliasing removal)
+ // 0.25 - almost off
+ // 0.00 - completely off
+ FxaaFloat fxaaQualitySubpix,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // The minimum amount of local contrast required to apply algorithm.
+ // 0.333 - too little (faster)
+ // 0.250 - low quality
+ // 0.166 - default
+ // 0.125 - high quality
+ // 0.063 - overkill (slower)
+ FxaaFloat fxaaQualityEdgeThreshold,
+ //
+ // Only used on FXAA Quality.
+ // This used to be the FXAA_QUALITY__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // 0.0833 - upper limit (default, the start of visible unfiltered edges)
+ // 0.0625 - high quality (faster)
+ // 0.0312 - visible limit (slower)
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_SHARPNESS define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_SHARPNESS for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only three safe values here: 2 and 4 and 8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // For all other platforms can be a non-power of two.
+ // 8.0 is sharper (default!!!)
+ // 4.0 is softer
+ // 2.0 is really soft (good only for vector graphics inputs)
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD define.
+ // It is here now to allow easier tuning.
+ // This does not effect PS3, as this needs to be compiled in.
+ // Use FXAA_CONSOLE__PS3_EDGE_THRESHOLD for PS3.
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 1/4 and 1/8.
+ // These options use the shaders ability to a free *|/ by 2|4|8.
+ // The console setting has a different mapping than the quality setting.
+ // Other platforms can use other values.
+ // 0.125 leaves less aliasing, but is softer (default!!!)
+ // 0.25 leaves more aliasing, and is sharper
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ //
+ // Only used on FXAA Console.
+ // This used to be the FXAA_CONSOLE__EDGE_THRESHOLD_MIN define.
+ // It is here now to allow easier tuning.
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ // This does not apply to PS3,
+ // PS3 was simplified to avoid more shader instructions.
+ // 0.06 - faster but more aliasing in darks
+ // 0.05 - default
+ // 0.04 - slower and less aliasing in darks
+ // Special notes when using FXAA_GREEN_AS_LUMA,
+ // Likely want to set this to zero.
+ // As colors that are mostly not-green
+ // will appear very dark in the green channel!
+ // Tune by looking at mostly non-green content,
+ // then start at zero and increase until aliasing is a problem.
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ //
+ // Extra constants for 360 FXAA Console only.
+ // Use zeros or anything else for other platforms.
+ // These must be in physical constant registers and NOT immedates.
+ // Immedates will result in compiler un-optimizing.
+ // {xyzw} = float4(1.0, -1.0, 0.25, -0.25)
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posM;
+ posM.x = pos.x;
+ posM.y = pos.y;
+ #if (FXAA_GATHER4_ALPHA == 1)
+ #if (FXAA_DISCARD == 0)
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ #endif
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat4 luma4A = FxaaTexAlpha4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffAlpha4(tex, posM, FxaaInt2(-1, -1));
+ #else
+ FxaaFloat4 luma4A = FxaaTexGreen4(tex, posM);
+ FxaaFloat4 luma4B = FxaaTexOffGreen4(tex, posM, FxaaInt2(-1, -1));
+ #endif
+ #if (FXAA_DISCARD == 1)
+ #define lumaM luma4A.w
+ #endif
+ #define lumaE luma4A.z
+ #define lumaS luma4A.x
+ #define lumaSE luma4A.y
+ #define lumaNW luma4B.w
+ #define lumaN luma4B.z
+ #define lumaW luma4B.x
+ #else
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, posM);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ #define lumaM rgbyM.w
+ #else
+ #define lumaM rgbyM.y
+ #endif
+ FxaaFloat lumaS = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaN = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat maxSM = max(lumaS, lumaM);
+ FxaaFloat minSM = min(lumaS, lumaM);
+ FxaaFloat maxESM = max(lumaE, maxSM);
+ FxaaFloat minESM = min(lumaE, minSM);
+ FxaaFloat maxWN = max(lumaN, lumaW);
+ FxaaFloat minWN = min(lumaN, lumaW);
+ FxaaFloat rangeMax = max(maxWN, maxESM);
+ FxaaFloat rangeMin = min(minWN, minESM);
+ FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;
+ FxaaFloat range = rangeMax - rangeMin;
+ FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);
+ FxaaBool earlyExit = range < rangeMaxClamped;
+/*--------------------------------------------------------------------------*/
+ if(earlyExit)
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ FxaaFloat lumaNW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #else
+ FxaaFloat lumaNE = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(1, -1), fxaaQualityRcpFrame.xy));
+ FxaaFloat lumaSW = FxaaLuma(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy));
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNS = lumaN + lumaS;
+ FxaaFloat lumaWE = lumaW + lumaE;
+ FxaaFloat subpixRcpRange = 1.0/range;
+ FxaaFloat subpixNSWE = lumaNS + lumaWE;
+ FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS;
+ FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNESE = lumaNE + lumaSE;
+ FxaaFloat lumaNWNE = lumaNW + lumaNE;
+ FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE;
+ FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNWSW = lumaNW + lumaSW;
+ FxaaFloat lumaSWSE = lumaSW + lumaSE;
+ FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);
+ FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);
+ FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;
+ FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE;
+ FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4;
+ FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE;
+ FxaaFloat lengthSign = fxaaQualityRcpFrame.x;
+ FxaaBool horzSpan = edgeHorz >= edgeVert;
+ FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;
+/*--------------------------------------------------------------------------*/
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;
+ FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat gradientN = lumaN - lumaM;
+ FxaaFloat gradientS = lumaS - lumaM;
+ FxaaFloat lumaNN = lumaN + lumaM;
+ FxaaFloat lumaSS = lumaS + lumaM;
+ FxaaBool pairN = abs(gradientN) >= abs(gradientS);
+ FxaaFloat gradient = max(abs(gradientN), abs(gradientS));
+ if(pairN) lengthSign = -lengthSign;
+ FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posB;
+ posB.x = posM.x;
+ posB.y = posM.y;
+ FxaaFloat2 offNP;
+ offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
+ offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
+ if(!horzSpan) posB.x += lengthSign * 0.5;
+ if( horzSpan) posB.y += lengthSign * 0.5;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 posN;
+ posN.x = posB.x - offNP.x * FXAA_QUALITY__P0;
+ posN.y = posB.y - offNP.y * FXAA_QUALITY__P0;
+ FxaaFloat2 posP;
+ posP.x = posB.x + offNP.x * FXAA_QUALITY__P0;
+ posP.y = posB.y + offNP.y * FXAA_QUALITY__P0;
+ FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0;
+ FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN));
+ FxaaFloat subpixE = subpixC * subpixC;
+ FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP));
+/*--------------------------------------------------------------------------*/
+ if(!pairN) lumaNN = lumaSS;
+ FxaaFloat gradientScaled = gradient * 1.0/4.0;
+ FxaaFloat lumaMM = lumaM - lumaNN * 0.5;
+ FxaaFloat subpixF = subpixD * subpixE;
+ FxaaBool lumaMLTZero = lumaMM < 0.0;
+/*--------------------------------------------------------------------------*/
+ lumaEndN -= lumaNN * 0.5;
+ lumaEndP -= lumaNN * 0.5;
+ FxaaBool doneN = abs(lumaEndN) >= gradientScaled;
+ FxaaBool doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1;
+ FxaaBool doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1;
+/*--------------------------------------------------------------------------*/
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 3)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 4)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 5)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 6)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 7)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 8)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 9)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 10)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 11)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_QUALITY__PS > 12)
+ if(doneNP) {
+ if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy));
+ if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy));
+ if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;
+ if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;
+ doneN = abs(lumaEndN) >= gradientScaled;
+ doneP = abs(lumaEndP) >= gradientScaled;
+ if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12;
+ if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12;
+ doneNP = (!doneN) || (!doneP);
+ if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12;
+ if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12;
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+ #endif
+/*--------------------------------------------------------------------------*/
+ }
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dstN = posM.x - posN.x;
+ FxaaFloat dstP = posP.x - posM.x;
+ if(!horzSpan) dstN = posM.y - posN.y;
+ if(!horzSpan) dstP = posP.y - posM.y;
+/*--------------------------------------------------------------------------*/
+ FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;
+ FxaaFloat spanLength = (dstP + dstN);
+ FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;
+ FxaaFloat spanLengthRcp = 1.0/spanLength;
+/*--------------------------------------------------------------------------*/
+ FxaaBool directionN = dstN < dstP;
+ FxaaFloat dst = min(dstN, dstP);
+ FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP;
+ FxaaFloat subpixG = subpixF * subpixF;
+ FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5;
+ FxaaFloat subpixH = subpixG * fxaaQualitySubpix;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0;
+ FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH);
+ if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;
+ if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;
+ #if (FXAA_DISCARD == 1)
+ return FxaaTexTop(tex, posM);
+ #else
+ return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM);
+ #endif
+}
+/*==========================================================================*/
+#endif
+
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC VERSION
+
+------------------------------------------------------------------------------
+Instead of using this on PC, I'd suggest just using FXAA Quality with
+ #define FXAA_QUALITY__PRESET 10
+Or
+ #define FXAA_QUALITY__PRESET 20
+Either are higher qualilty and almost as fast as this on modern PC GPUs.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+FxaaFloat4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaNw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xy));
+ FxaaFloat lumaSw = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.xw));
+ FxaaFloat lumaNe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zy));
+ FxaaFloat lumaSe = FxaaLuma(FxaaTexTop(tex, fxaaConsolePosPos.zw));
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaFloat lumaM = rgbyM.w;
+ #else
+ FxaaFloat lumaM = rgbyM.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNwSw = max(lumaNw, lumaSw);
+ lumaNe += 1.0/384.0;
+ FxaaFloat lumaMinNwSw = min(lumaNw, lumaSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxNeSe = max(lumaNe, lumaSe);
+ FxaaFloat lumaMinNeSe = min(lumaNe, lumaSe);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMax = max(lumaMaxNeSe, lumaMaxNwSw);
+ FxaaFloat lumaMin = min(lumaMinNeSe, lumaMinNwSw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMaxScaled = lumaMax * fxaaConsoleEdgeThreshold;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat lumaMinM = min(lumaMin, lumaM);
+ FxaaFloat lumaMaxScaledClamped = max(fxaaConsoleEdgeThresholdMin, lumaMaxScaled);
+ FxaaFloat lumaMaxM = max(lumaMax, lumaM);
+ FxaaFloat dirSwMinusNe = lumaSw - lumaNe;
+ FxaaFloat lumaMaxSubMinM = lumaMaxM - lumaMinM;
+ FxaaFloat dirSeMinusNw = lumaSe - lumaNw;
+ if(lumaMaxSubMinM < lumaMaxScaledClamped) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir;
+ dir.x = dirSwMinusNe + dirSeMinusNw;
+ dir.y = dirSwMinusNe - dirSeMinusNw;
+/*--------------------------------------------------------------------------*/
+ FxaaFloat2 dir1 = normalize(dir.xy);
+ FxaaFloat4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * fxaaConsoleRcpFrameOpt.zw);
+ FxaaFloat4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * fxaaConsoleRcpFrameOpt.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * fxaaConsoleEdgeSharpness;
+ FxaaFloat2 dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * fxaaConsoleRcpFrameOpt2.zw);
+ FxaaFloat4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * fxaaConsoleRcpFrameOpt2.zw);
+/*--------------------------------------------------------------------------*/
+ FxaaFloat4 rgbyA = rgbyN1 + rgbyP1;
+ FxaaFloat4 rgbyB = ((rgbyN2 + rgbyP2) * 0.25) + (rgbyA * 0.25);
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ FxaaBool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ #else
+ FxaaBool twoTap = (rgbyB.y < lumaMin) || (rgbyB.y > lumaMax);
+ #endif
+ if(twoTap) rgbyB.xyz = rgbyA.xyz * 0.5;
+ return rgbyB; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+This optimized version thanks to suggestions from Andy Luedke.
+Should be fully tex bound in all cases.
+As of the FXAA 3.11 release, I have still not tested this code,
+however I fixed a bug which was in both FXAA 3.9 and FXAA 3.10.
+And note this is replacing the old unoptimized version.
+If it does not work, please let me know so I can fix it.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+[reduceTempRegUsage(4)]
+float4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+ float4 lumaNwNeSwSe;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ asm {
+ tfetch2D lumaNwNeSwSe.w___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._w__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.__w_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.___w, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #else
+ asm {
+ tfetch2D lumaNwNeSwSe.y___, tex, pos.xy, OffsetX = -0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe._y__, tex, pos.xy, OffsetX = 0.5, OffsetY = -0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.__y_, tex, pos.xy, OffsetX = -0.5, OffsetY = 0.5, UseComputedLOD=false
+ tfetch2D lumaNwNeSwSe.___y, tex, pos.xy, OffsetX = 0.5, OffsetY = 0.5, UseComputedLOD=false
+ };
+ #endif
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+ float2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ float lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ float lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ float4 rgbyM = tex2Dlod(tex, float4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ float lumaMinM = min(lumaMin, rgbyM.w);
+ float lumaMaxM = max(lumaMax, rgbyM.w);
+ #else
+ float lumaMinM = min(lumaMin, rgbyM.y);
+ float lumaMaxM = max(lumaMax, rgbyM.y);
+ #endif
+ if((lumaMaxM - lumaMinM) < max(fxaaConsoleEdgeThresholdMin, lumaMax * fxaaConsoleEdgeThreshold)) return rgbyM;
+/*--------------------------------------------------------------------------*/
+ float2 dir;
+ dir.x = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.yyxx);
+ dir.y = dot(lumaNwNeSwSe, fxaaConsole360ConstDir.xyxy);
+ dir = normalize(dir);
+/*--------------------------------------------------------------------------*/
+ float4 dir1 = dir.xyxy * fxaaConsoleRcpFrameOpt.xyzw;
+/*--------------------------------------------------------------------------*/
+ float4 dir2;
+ float dirAbsMinTimesC = min(abs(dir.x), abs(dir.y)) * fxaaConsoleEdgeSharpness;
+ dir2 = saturate(fxaaConsole360ConstDir.zzww * dir.xyxy / dirAbsMinTimesC + 0.5);
+ dir2 = dir2 * fxaaConsole360RcpFrameOpt2.xyxy + fxaaConsole360RcpFrameOpt2.zwzw;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyN1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.xy, 0.0, 0.0));
+ float4 rgbyP1 = tex2Dlod(fxaaConsole360TexExpBiasNegOne, float4(pos.xy + dir1.zw, 0.0, 0.0));
+ float4 rgbyN2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.xy, 0.0, 0.0));
+ float4 rgbyP2 = tex2Dlod(fxaaConsole360TexExpBiasNegTwo, float4(pos.xy + dir2.zw, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+ float4 rgbyA = rgbyN1 + rgbyP1;
+ float4 rgbyB = rgbyN2 + rgbyP2 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ float4 rgbyR = ((FxaaLuma(rgbyB) - lumaMax) > 0.0) ? rgbyA : rgbyB;
+ rgbyR = ((FxaaLuma(rgbyB) - lumaMin) > 0.0) ? rgbyR : rgbyA;
+ return rgbyR; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+ #else
+ lumaNe.y += half(1.0/512.0);
+ dir.x = -lumaNe.y;
+ dir.z = -lumaNe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+ #else
+ dir.x += lumaSw.y;
+ dir.z += lumaSw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+ #else
+ dir.x -= lumaNw.y;
+ dir.z += lumaNw.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+ #else
+ dir.x += lumaSe.y;
+ dir.z -= lumaSe.y;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #else
+ half lumaMin = min(min(lumaNw.y, lumaSw.y), min(lumaNe.y, lumaSe.y));
+ half lumaMax = max(max(lumaNw.y, lumaSw.y), max(lumaNe.y, lumaSe.y));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+Use of FXAA_GREEN_AS_LUMA currently adds a cycle (16 clks).
+Will look at fixing this for FXAA 3.12.
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma regcount 7
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // See FXAA Quality FxaaPixelShader() source for docs on Inputs!
+ FxaaFloat2 pos,
+ FxaaFloat4 fxaaConsolePosPos,
+ FxaaTex tex,
+ FxaaTex fxaaConsole360TexExpBiasNegOne,
+ FxaaTex fxaaConsole360TexExpBiasNegTwo,
+ FxaaFloat2 fxaaQualityRcpFrame,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt,
+ FxaaFloat4 fxaaConsoleRcpFrameOpt2,
+ FxaaFloat4 fxaaConsole360RcpFrameOpt2,
+ FxaaFloat fxaaQualitySubpix,
+ FxaaFloat fxaaQualityEdgeThreshold,
+ FxaaFloat fxaaQualityEdgeThresholdMin,
+ FxaaFloat fxaaConsoleEdgeSharpness,
+ FxaaFloat fxaaConsoleEdgeThreshold,
+ FxaaFloat fxaaConsoleEdgeThresholdMin,
+ FxaaFloat4 fxaaConsole360ConstDir
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+ #else
+ half lumaNe = rgbyNe.y + half(1.0/512.0);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+ #else
+ half lumaSwNegNe = lumaSw.y - lumaNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(fxaaConsolePosPos.xy, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+ #else
+ half lumaMaxNwSw = max(lumaNw.y, lumaSw.y);
+ half lumaMinNwSw = min(lumaNw.y, lumaSw.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(fxaaConsolePosPos.zw, 0, 0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+ #else
+ half dirZ = lumaNw.y + lumaSwNegNe;
+ half dirX = -lumaNw.y + lumaSwNegNe;
+ #endif
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+ #else
+ dir.x = lumaSe.y + dirX;
+ dir.z = -lumaSe.y + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__PS3_EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+ #else
+ half lumaMaxNeSe = max(lumaNe, lumaSe.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * fxaaConsoleRcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ #else
+ half lumaMaxM = max(lumaMax, rgbyM.y);
+ half lumaMinM = min(lumaMin, rgbyM.y);
+ #endif
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * fxaaConsoleRcpFrameOpt2.zw;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__PS3_EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ #if (FXAA_GREEN_AS_LUMA == 0)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ #else
+ bool twoTapLt = rgby2.y < lumaMin;
+ bool twoTapGt = rgby2.y > lumaMax;
+ #endif
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
diff --git a/res/effectlib/Fxaa3_8.glsllib b/res/effectlib/Fxaa3_8.glsllib
new file mode 100644
index 0000000..620f565
--- /dev/null
+++ b/res/effectlib/Fxaa3_8.glsllib
@@ -0,0 +1,1423 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 - 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$
+**
+****************************************************************************/
+
+
+/*============================================================================
+
+
+ NVIDIA FXAA III.8 by TIMOTHY LOTTES
+
+
+------------------------------------------------------------------------------
+ INTEGRATION CHECKLIST
+------------------------------------------------------------------------------
+(1.)
+In the shader source,
+setup defines for the desired configuration.
+Example,
+
+ #define FXAA_PC 1
+ #define FXAA_HLSL_3 1
+ #define FXAA_LINEAR 1
+
+(2.)
+Then include this file,
+
+
+
+(3.)
+Then call the FXAA pixel shader from within your desired shader,
+
+ return FxaaPixelShader(pos, posPos, tex, rcpFrame, rcpFrameOpt);
+
+(4.)
+Insure pass prior to FXAA outputs RGBL.
+See next section.
+
+(5.)
+Setup engine to provide "rcpFrame" and "rcpFrameOpt" constants.
+Not using constants will result in a performance loss.
+
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ float2 rcpFrame
+
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+
+(6.)
+Have FXAA vertex shader run as a full screen triangle,
+and output "pos" and "posPos" such that inputs in the pixel shader provide,
+
+ // {xy} = center of pixel
+ float2 pos,
+
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+
+(7.)
+Insure the texture sampler used by FXAA is set to bilinear filtering.
+
+
+------------------------------------------------------------------------------
+ INTEGRATION - RGBL AND COLORSPACE
+------------------------------------------------------------------------------
+FXAA3 requires RGBL as input.
+
+RGB should be LDR (low dynamic range).
+Specifically do FXAA after tonemapping.
+
+RGB data as returned by a texture fetch can be linear or non-linear.
+Note an "sRGB format" texture counts as linear,
+because the result of a texture fetch is linear data.
+Regular "RGBA8" textures in the sRGB colorspace are non-linear.
+If a texture fetch results linear data the following is required,
+
+ #define FXAA_LINEAR 1
+
+Otherwise,
+
+ #define FXAA_LINEAR 0
+
+Luma must be stored in the alpha channel prior to running FXAA.
+This luma value must be gamma 2.0 encoded if using FXAA_LINEAR 1.
+If using FXAA_LINEAR 0, luma should match the perceptual space used for RGB.
+
+Example pass before FXAA where output is gamma 2.0 encoded,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.rgb = sqrt(color.rgb); // gamma 2.0 color output
+ color.a = dot(color.rgb, float3(0.299, 0.587, 0.114)); // compute luma
+ return color;
+
+Another example where output is linear encoded,
+say for instance writing to an sRGB formated render target,
+where the render target does the conversion back to sRGB after blending,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ return color;
+
+To use FXAA,
+
+ color.rgb = ToneMap(color.rgb); // linear color output
+ color.a = sqrt(dot(color.rgb, float3(0.299, 0.587, 0.114))); // compute luma
+ return color;
+
+Getting luma correct is required for the algorithm to work correctly.
+
+
+------------------------------------------------------------------------------
+ COMPLEX INTEGRATION
+------------------------------------------------------------------------------
+Q. What if the engine is blending into RGB before wanting to run FXAA?
+
+A. In the last opaque pass prior to FXAA,
+ have the pass write out luma into alpha.
+ Then blend into RGB only.
+ FXAA should be able to run ok
+ assuming the blending pass did not any add aliasing.
+ This should be the common case for particles and common blending passes.
+
+============================================================================*/
+
+/*============================================================================
+
+ INTEGRATION KNOBS
+
+============================================================================*/
+//
+// FXAA_PS3 and FXAA_360 choose the console algorithm (FXAA3 CONSOLE).
+//
+// 1 = Use API.
+// 0 = Don't use API.
+//
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PS3
+ #define FXAA_PS3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_360
+ #define FXAA_360 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_PC
+ //
+ // FXAA Quality
+ // The high quality PC algorithm.
+ //
+ #define FXAA_PC 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_PC_CONSOLE
+ //
+ // The console algorithm for PC is included
+ // for developers targeting really low spec machines.
+ //
+ #define FXAA_PC_CONSOLE 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_120
+ #define FXAA_GLSL_120 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GLSL_130
+ #define FXAA_GLSL_130 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_3
+ #define FXAA_HLSL_3 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_4
+ #define FXAA_HLSL_4 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_HLSL_5
+ #define FXAA_HLSL_5 0
+#endif
+/*==========================================================================*/
+#ifndef FXAA_EARLY_EXIT
+ //
+ // Controls algorithm's early exit path.
+ // On PS3 turning this on adds 2 cycles to the shader.
+ // On 360 turning this off adds 10ths of a millisecond to the shader.
+ // Turning this off on console will result in a more blurry image.
+ // So this defaults to on.
+ //
+ // 1 = On.
+ // 0 = Off.
+ //
+ #define FXAA_EARLY_EXIT 1
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_DISCARD
+ //
+ // Only valid for PC OpenGL currently.
+ //
+ // 1 = Use discard on pixels which don't need AA.
+ // For APIs which enable concurrent TEX+ROP from same surface.
+ // 0 = Return unchanged color on pixels which don't need AA.
+ //
+ #define FXAA_DISCARD 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_LINEAR
+ //
+ // 0 = Work in non-linear color space.
+ // Use this for standard 32-bit RGBA formats.
+ //
+ // 1 = Work in RGB=linear, A=non-linear luma.
+ // Use this for sRGB and FP16 formats.
+ // Works with either FXAA_ALGORITHM = 1 or 0.
+ //
+ #define FXAA_LINEAR 0
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_FAST_PIXEL_OFFSET
+ //
+ // Used for GLSL 120 only.
+ //
+ // 1 = GL API supports fast pixel offsets
+ // 0 = do not use fast pixel offsets
+ //
+ #ifdef GL_EXT_gpu_shader4
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_FAST_PIXEL_OFFSET 1
+ #endif
+ #ifndef FXAA_FAST_PIXEL_OFFSET
+ #define FXAA_FAST_PIXEL_OFFSET 0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_GATHER4_ALPHA
+ //
+ // 1 = API supports gather4 on alpha channel.
+ // 0 = API does not support gather4 on alpha channel.
+ //
+#ifdef GL_ES
+ #if __VERSION__ >= 310
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#else
+ #if (FXAA_HLSL_5 == 1)
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_ARB_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_NV_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifdef GL_EXT_gpu_shader5
+ #define FXAA_GATHER4_ALPHA 1
+ #endif
+ #ifndef FXAA_GATHER4_ALPHA
+ #define FXAA_GATHER4_ALPHA 0
+ #endif
+#endif
+#endif
+
+/*============================================================================
+ FXAA CONSOLE - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_CONSOLE__EDGE_SHARPNESS
+ //
+ // Consoles the sharpness of edges.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 4 and 8.
+ // These options use the shaders ability to a free *|/ by 4|8.
+ //
+ // 8.0 is sharper
+ // 4.0 is softer
+ //
+ #if 1
+ #define FXAA_CONSOLE__EDGE_SHARPNESS 8.0
+ #else
+ #define FXAA_CONSOLE__EDGE_SHARPNESS 4.0
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__EDGE_THRESHOLD
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // Due to the PS3 being ALU bound,
+ // there are only two safe values here: 0.25 and 0.125.
+ // These options use the shaders ability to a free *|/ by 4|8.
+ //
+ // 0.125 leaves less aliasing, but is softer
+ // 0.25 leaves more aliasing, and is sharper
+ //
+ #if 1
+ #define FXAA_CONSOLE__EDGE_THRESHOLD 0.125
+ #else
+ #define FXAA_CONSOLE__EDGE_THRESHOLD 0.25
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_CONSOLE__EDGE_THRESHOLD_MIN
+ //
+ // Trims the algorithm from processing darks.
+ // The console setting has a different mapping than the quality setting.
+ //
+ // This only applies when FXAA_EARLY_EXIT is 1.
+ //
+ // This does not apply to PS3.
+ // PS3 was simplified to avoid more shader instructions.
+ //
+ #define FXAA_CONSOLE__EDGE_THRESHOLD_MIN 0.05
+#endif
+
+/*============================================================================
+ FXAA QUALITY - TUNING KNOBS
+============================================================================*/
+#ifndef FXAA_QUALITY__EDGE_THRESHOLD
+ //
+ // The minimum amount of local contrast required to apply algorithm.
+ //
+ // 1/3 - too little
+ // 1/4 - low quality
+ // 1/6 - default
+ // 1/8 - high quality
+ // 1/16 - overkill
+ //
+ #define FXAA_QUALITY__EDGE_THRESHOLD (1.0/6.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__EDGE_THRESHOLD_MIN
+ //
+ // Trims the algorithm from processing darks.
+ //
+ // 1/32 - visible limit
+ // 1/16 - high quality
+ // 1/12 - upper limit (default, the start of visible unfiltered edges)
+ //
+ #define FXAA_QUALITY__EDGE_THRESHOLD_MIN (1.0/12.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__SUBPIX_CAP
+ //
+ // Insures fine detail is not completely removed.
+ // This partly overrides FXAA_SUBPIX_TRIM.
+ //
+ // 3/4 - default amount of filtering
+ // 7/8 - high amount of filtering
+ // 1 - no capping of filtering
+ //
+ #define FXAA_QUALITY__SUBPIX_CAP (3.0/4.0)
+#endif
+/*--------------------------------------------------------------------------*/
+#ifndef FXAA_QUALITY__SUBPIX_TRIM
+ //
+ // Controls removal of sub-pixel aliasing,
+ //
+ // 1/2 - low removal (sharper but more sub-pixel aliasing)
+ // 1/3 - medium removal
+ // 1/4 - default removal
+ // 1/8 - high removal
+ // 0 - complete removal (softer but less sub-pixel aliasing)
+ //
+ #define FXAA_QUALITY__SUBPIX_TRIM (1.0/4.0)
+#endif
+
+
+/*============================================================================
+
+ API PORTING
+
+============================================================================*/
+#if FXAA_GLSL_120
+ // Requires,
+ // #version 120
+ // And at least,
+ // #extension GL_EXT_gpu_shader4 : enable
+ // (or set FXAA_FAST_PIXEL_OFFSET 1 to work like DX9)
+ #define half float
+ #define half2 vec2
+ #define half3 vec3
+ #define half4 vec4
+ #define int2 ivec2
+ #define float2 vec2
+ #define float3 vec3
+ #define float4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaDiscard discard
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaLerp(x,y,s) mix(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) texture2DLod(t, p, 0.0)
+ #if (FXAA_FAST_PIXEL_OFFSET == 1)
+ #define FxaaTexOff(t, p, o, r) texture2DLodOffset(t, p, 0.0, o)
+ #else
+ #define FxaaTexOff(t, p, o, r) texture2DLod(t, p + (o * r), 0.0)
+ #endif
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_GLSL_130
+ // Requires "#version 130" or better
+ #define half float
+ #define half2 vec2
+ #define half3 vec3
+ #define half4 vec4
+ #define int2 ivec2
+ #define float2 vec2
+ #define float3 vec3
+ #define float4 vec4
+ #define FxaaInt2 ivec2
+ #define FxaaFloat2 vec2
+ #define FxaaFloat3 vec3
+ #define FxaaFloat4 vec4
+ #define FxaaDiscard discard
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) clamp(x, 0.0, 1.0)
+ #define FxaaLerp(x,y,s) mix(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) textureLod(t, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
+ #if (FXAA_GATHER4_ALPHA == 1)
+ // use #extension GL_ARB_gpu_shader5 : enable
+ #define FxaaTexAlpha4(t, p, r) textureGather(t, p, 3)
+ #define FxaaTexOffAlpha4(t, p, o, r) textureGatherOffset(t, p, o, 3)
+ #endif
+#endif
+/*--------------------------------------------------------------------------*/
+#if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1)
+ #define int2 float2
+ #define FxaaInt2 float2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ #define FxaaTex sampler2D
+ #define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))
+ #define FxaaTexOff(t, p, o, r) tex2Dlod(t, float4(p + (o * r), 0, 0))
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_HLSL_4
+ #define FxaaInt2 int2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+#endif
+/*--------------------------------------------------------------------------*/
+#if FXAA_HLSL_5
+ #define FxaaInt2 int2
+ #define FxaaFloat2 float2
+ #define FxaaFloat3 float3
+ #define FxaaFloat4 float4
+ #define FxaaDiscard clip(-1)
+ #define FxaaDot3(a, b) dot(a, b)
+ #define FxaaSat(x) saturate(x)
+ #define FxaaLerp(x,y,s) lerp(x,y,s)
+ struct FxaaTex { SamplerState smpl; Texture2D tex; };
+ #define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
+ #define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
+ #define FxaaTexAlpha4(t, p, r) t.tex.GatherAlpha(t.smpl, p)
+ #define FxaaTexOffAlpha4(t, p, o, r) t.tex.GatherAlpha(t.smpl, p, o)
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - 360 PIXEL SHADER
+
+------------------------------------------------------------------------------
+Might be some optimizations left here,
+as of this latest change didn't have a PIX dump to verify if TEX bound.
+============================================================================*/
+#if (FXAA_360 == 1)
+/*--------------------------------------------------------------------------*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = alpha output is junk value
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PC version of FXAA Console
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ half4 lumaNwNeSwSe;
+ lumaNwNeSwSe.x = FxaaTexTop(tex, posPos.xy).w;
+ lumaNwNeSwSe.y = FxaaTexTop(tex, posPos.zy).w;
+ lumaNwNeSwSe.z = FxaaTexTop(tex, posPos.xw).w;
+ lumaNwNeSwSe.w = FxaaTexTop(tex, posPos.zw).w;
+/*--------------------------------------------------------------------------*/
+ half4 rgbyM = FxaaTexTop(tex, pos.xy);
+/*--------------------------------------------------------------------------*/
+ lumaNwNeSwSe.y += 1.0/384.0;
+/*--------------------------------------------------------------------------*/
+ half2 lumaMinTemp = min(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+ half2 lumaMaxTemp = max(lumaNwNeSwSe.xy, lumaNwNeSwSe.zw);
+/*--------------------------------------------------------------------------*/
+ half lumaMin = min(lumaMinTemp.x, lumaMinTemp.y);
+ half lumaMax = max(lumaMaxTemp.x, lumaMaxTemp.y);
+/*--------------------------------------------------------------------------*/
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ half2 dir;
+ dir.x = dot(lumaNwNeSwSe, float4(-1.0, -1.0, 1.0, 1.0));
+ dir.y = dot(lumaNwNeSwSe, float4( 1.0, -1.0, 1.0,-1.0));
+/*--------------------------------------------------------------------------*/
+ half2 dir1;
+ dir1 = normalize(dir.xy);
+/*--------------------------------------------------------------------------*/
+ half dirAbsMinTimesC = min(abs(dir1.x), abs(dir1.y)) * FXAA_CONSOLE__EDGE_SHARPNESS;
+ half2 dir2;
+ dir2 = clamp(dir1.xy / dirAbsMinTimesC, -2.0, 2.0);
+/*--------------------------------------------------------------------------*/
+ half4 rgbyN1 = FxaaTexTop(tex, pos.xy - dir1 * rcpFrameOpt.zw);
+ half4 rgbyP1 = FxaaTexTop(tex, pos.xy + dir1 * rcpFrameOpt.zw);
+ half4 rgbyN2 = FxaaTexTop(tex, pos.xy - dir2 * rcpFrameOpt.xy);
+ half4 rgbyP2 = FxaaTexTop(tex, pos.xy + dir2 * rcpFrameOpt.xy);
+/*--------------------------------------------------------------------------*/
+ half4 rgbyA = rgbyN1 * 0.5 + rgbyP1 * 0.5;
+ half4 rgbyB = rgbyN2 * 0.25 + rgbyP2 * 0.25 + rgbyA * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool twoTap = (rgbyB.w < lumaMin) || (rgbyB.w > lumaMax);
+ if(twoTap) rgbyB.xyz = rgbyA.xyz;
+ return rgbyB;
+}
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (NO EARLY EXIT)
+
+==============================================================================
+The code below does not exactly match the assembly.
+I have a feeling that 12 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.z(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h0.w(TRUE), v5.xwxx, #0
+ 6: addh h0.z(TRUE), -h2, h0.w
+ 7: texpkb h1.w(TRUE), v5, #0
+ 9: addh h0.x(TRUE), h0.z, -h1.w
+ 10: addh h3.w(TRUE), h0.z, h1
+ 11: texpkb h2.w(TRUE), v5.zwzz, #0
+ 13: addh h0.z(TRUE), h3.w, -h2.w
+ 14: addh h0.x(TRUE), h2.w, h0
+ 15: nrmh h1.xz(TRUE), h0_n
+ 16: minh_m8 h0.x(TRUE), |h1|, |h1.z|
+ 17: maxh h4.w(TRUE), h0, h1
+ 18: divx h2.xy(TRUE), h1_n.xzzw, h0_n
+ 19: movr r1.zw(TRUE), v4.xxxy
+ 20: madr r2.xz(TRUE), -h1, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zzww, r1.zzww
+ 22: minh h5.w(TRUE), h0, h1
+ 23: texpkb h0(TRUE), r2.xzxx, #0
+ 25: madr r0.zw(TRUE), h1.xzxz, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w), r1
+ 27: maxh h4.x(TRUE), h2.z, h2.w
+ 28: texpkb h1(TRUE), r0.zwzz, #0
+ 30: addh_d2 h1(TRUE), h0, h1
+ 31: madr r0.xy(TRUE), -h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 33: texpkb h0(TRUE), r0, #0
+ 35: minh h4.z(TRUE), h2, h2.w
+ 36: fenct TRUE
+ 37: madr r1.xy(TRUE), h2, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 39: texpkb h2(TRUE), r1, #0
+ 41: addh_d2 h0(TRUE), h0, h2
+ 42: maxh h2.w(TRUE), h4, h4.x
+ 43: minh h2.x(TRUE), h5.w, h4.z
+ 44: addh_d2 h0(TRUE), h0, h1
+ 45: slth h2.x(TRUE), h0.w, h2
+ 46: sgth h2.w(TRUE), h0, h2
+ 47: movh h0(TRUE), h0
+ 48: addx.c0 rc(TRUE), h2, h2.w
+ 49: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB1 | add | 2: ADDh h2.z, h0.--w-, const.--x-;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h0.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB1 | add | 6: ADDh h0.z,-h2, h0.--w-;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h1.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 9: ADDh h0.x, h0.z---,-h1.w---;
+ | SCB1 | add | 10: ADDh h3.w, h0.---z, h1;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h2.w---, h0;
+ | SCB1 | add | 13: ADDh h0.z, h3.--w-,-h2.--w-;
+ | | |
+ 5 | SCT1 | mov | 15: NRMh h1.xz, h0;
+ | SRB | nrm | 15: NRMh h1.xz, h0;
+ | SCB0 | min | 16: MINh*8 h0.x, |h1|, |h1.z---|;
+ | SCB1 | max | 17: MAXh h4.w, h0, h1;
+ | | |
+ 6 | SCT0 | div | 18: DIVx h2.xy, h1.xz--, h0;
+ | SCT1 | mov | 19: MOVr r1.zw, g[TEX0].--xy;
+ | SCB0 | mad | 20: MADr r2.xz,-h1, const.z-w-, r1.z-w-;
+ | SCB1 | min | 22: MINh h5.w, h0, h1;
+ | | |
+ 7 | SCT0/1 | mov | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | TEX | txl | 23: TXLr h0, r2.xzxx, const.xxxx, TEX0;
+ | SCB0 | max | 27: MAXh h4.x, h2.z---, h2.w---;
+ | SCB1 | mad | 25: MADr r0.zw, h1.--xz, const, r1;
+ | | |
+ 8 | SCT0/1 | mov | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | TEX | txl | 28: TXLr h1, r0.zwzz, const.xxxx, TEX0;
+ | SCB0/1 | add | 30: ADDh/2 h1, h0, h1;
+ | | |
+ 9 | SCT0 | mad | 31: MADr r0.xy,-h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 33: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB1 | min | 35: MINh h4.z, h2, h2.--w-;
+ | | |
+ 10 | SCT0 | mad | 37: MADr r1.xy, h2, const.xy--, r1.zw--;
+ | SCT1 | mov | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | TEX | txl | 39: TXLr h2, r1, const.zzzz, TEX0;
+ | SCB0/1 | add | 41: ADDh/2 h0, h0, h2;
+ | | |
+ 11 | SCT0 | min | 43: MINh h2.x, h5.w---, h4.z---;
+ | SCT1 | max | 42: MAXh h2.w, h4, h4.---x;
+ | SCB0/1 | add | 44: ADDh/2 h0, h0, h1;
+ | | |
+ 12 | SCT0 | set | 45: SLTh h2.x, h0.w---, h2;
+ | SCT1 | set | 46: SGTh h2.w, h0, h2;
+ | SCB0/1 | mul | 47: MOVh h0, h0;
+ | | |
+ 13 | SCT0 | mad | 48: ADDxc0_s rc, h2, h2.w---;
+ | SCB0/1 | mul | 49: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 0% 0% 50%
+ 6: 100% 0% 75%
+ 7: 0% 100% 75%
+ 8: 0% 100% 100%
+ 9: 0% 100% 25%
+ 10: 0% 100% 100%
+ 11: 50% 0% 100%
+ 12: 50% 0% 100%
+ 13: 25% 0% 100%
+
+MEAN: 17% 61% 67%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 0% 100%
+ 2: 0% 0% 100% 0% 100%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 0% 0% 0% 100% 100%
+ 6: 100% 100% 0% 100% 100%
+ 7: 0% 0% 100% 100% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 0% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 100% 100% 0% 100% 100%
+ 12: 100% 100% 0% 100% 100%
+ 13: 100% 0% 0% 100% 100%
+
+MEAN: 30% 23% 61% 76% 100%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 13 cycles, 3 r regs, 923,076,923 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 0)
+/*--------------------------------------------------------------------------*/
+#pragma disablepc all
+#pragma option O3
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ sampler2D tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PS3
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 dir;
+ half4 lumaNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0));
+ lumaNe.w += half(1.0/512.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0));
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0));
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0));
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+/*--------------------------------------------------------------------------*/
+// (5)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (7)
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+// (8)
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (11)
+ // compilier moves these scalar ops up to other cycles
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (12)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+/*--------------------------------------------------------------------------*/
+// (13)
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - OPTIMIZED PS3 PIXEL SHADER (WITH EARLY EXIT)
+
+==============================================================================
+The code mostly matches the assembly.
+I have a feeling that 14 cycles is possible, but was not able to get there.
+Might have to increase register count to get full performance.
+Note this shader does not use perspective interpolation.
+
+Use the following cgc options,
+
+ --fenable-bx2 --fastmath --fastprecision --nofloatbindings
+
+------------------------------------------------------------------------------
+ NVSHADERPERF OUTPUT
+------------------------------------------------------------------------------
+For reference and to aid in debug, output of NVShaderPerf should match this,
+
+Shader to schedule:
+ 0: texpkb h0.w(TRUE), v5.zyxx, #0
+ 2: addh h2.y(TRUE), h0.w, constant(0.001953, 0.000000, 0.000000, 0.000000).x
+ 4: texpkb h1.w(TRUE), v5.xwxx, #0
+ 6: addh h0.x(TRUE), h1.w, -h2.y
+ 7: texpkb h2.w(TRUE), v5.zwzz, #0
+ 9: minh h4.w(TRUE), h2.y, h2
+ 10: maxh h5.x(TRUE), h2.y, h2.w
+ 11: texpkb h0.w(TRUE), v5, #0
+ 13: addh h3.w(TRUE), -h0, h0.x
+ 14: addh h0.x(TRUE), h0.w, h0
+ 15: addh h0.z(TRUE), -h2.w, h0.x
+ 16: addh h0.x(TRUE), h2.w, h3.w
+ 17: minh h5.y(TRUE), h0.w, h1.w
+ 18: nrmh h2.xz(TRUE), h0_n
+ 19: minh_m8 h2.w(TRUE), |h2.x|, |h2.z|
+ 20: divx h4.xy(TRUE), h2_n.xzzw, h2_n.w
+ 21: movr r1.zw(TRUE), v4.xxxy
+ 22: maxh h2.w(TRUE), h0, h1
+ 23: fenct TRUE
+ 24: madr r0.xy(TRUE), -h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 26: texpkb h0(TRUE), r0, #0
+ 28: maxh h5.x(TRUE), h2.w, h5
+ 29: minh h5.w(TRUE), h5.y, h4
+ 30: madr r1.xy(TRUE), h2.xzzw, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).zwzz, r1.zwzz
+ 32: texpkb h2(TRUE), r1, #0
+ 34: addh_d2 h2(TRUE), h0, h2
+ 35: texpkb h1(TRUE), v4, #0
+ 37: maxh h5.y(TRUE), h5.x, h1.w
+ 38: minh h4.w(TRUE), h1, h5
+ 39: madr r0.xy(TRUE), -h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 41: texpkb h0(TRUE), r0, #0
+ 43: addh_m8 h5.z(TRUE), h5.y, -h4.w
+ 44: madr r2.xy(TRUE), h4, constant(cConst5.x, cConst5.y, cConst5.z, cConst5.w).xyxx, r1.zwzz
+ 46: texpkb h3(TRUE), r2, #0
+ 48: addh_d2 h0(TRUE), h0, h3
+ 49: addh_d2 h3(TRUE), h0, h2
+ 50: movh h0(TRUE), h3
+ 51: slth h3.x(TRUE), h3.w, h5.w
+ 52: sgth h3.w(TRUE), h3, h5.x
+ 53: addx.c0 rc(TRUE), h3.x, h3
+ 54: slth.c0 rc(TRUE), h5.z, h5
+ 55: movh h0(c0.NE.w), h2
+ 56: movh h0(c0.NE.x), h1
+
+IPU0 ------ Simplified schedule: --------
+Pass | Unit | uOp | PC: Op
+-----+--------+------+-------------------------
+ 1 | SCT0/1 | mov | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | TEX | txl | 0: TXLr h0.w, g[TEX1].zyxx, const.xxxx, TEX0;
+ | SCB0 | add | 2: ADDh h2.y, h0.-w--, const.-x--;
+ | | |
+ 2 | SCT0/1 | mov | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | TEX | txl | 4: TXLr h1.w, g[TEX1].xwxx, const.xxxx, TEX0;
+ | SCB0 | add | 6: ADDh h0.x, h1.w---,-h2.y---;
+ | | |
+ 3 | SCT0/1 | mov | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | TEX | txl | 7: TXLr h2.w, g[TEX1].zwzz, const.xxxx, TEX0;
+ | SCB0 | max | 10: MAXh h5.x, h2.y---, h2.w---;
+ | SCB1 | min | 9: MINh h4.w, h2.---y, h2;
+ | | |
+ 4 | SCT0/1 | mov | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | TEX | txl | 11: TXLr h0.w, g[TEX1], const.xxxx, TEX0;
+ | SCB0 | add | 14: ADDh h0.x, h0.w---, h0;
+ | SCB1 | add | 13: ADDh h3.w,-h0, h0.---x;
+ | | |
+ 5 | SCT0 | mad | 16: ADDh h0.x, h2.w---, h3.w---;
+ | SCT1 | mad | 15: ADDh h0.z,-h2.--w-, h0.--x-;
+ | SCB0 | min | 17: MINh h5.y, h0.-w--, h1.-w--;
+ | | |
+ 6 | SCT1 | mov | 18: NRMh h2.xz, h0;
+ | SRB | nrm | 18: NRMh h2.xz, h0;
+ | SCB1 | min | 19: MINh*8 h2.w, |h2.---x|, |h2.---z|;
+ | | |
+ 7 | SCT0 | div | 20: DIVx h4.xy, h2.xz--, h2.ww--;
+ | SCT1 | mov | 21: MOVr r1.zw, g[TEX0].--xy;
+ | SCB1 | max | 22: MAXh h2.w, h0, h1;
+ | | |
+ 8 | SCT0 | mad | 24: MADr r0.xy,-h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | TEX | txl | 26: TXLr h0, r0, const.xxxx, TEX0;
+ | SCB0 | max | 28: MAXh h5.x, h2.w---, h5;
+ | SCB1 | min | 29: MINh h5.w, h5.---y, h4;
+ | | |
+ 9 | SCT0 | mad | 30: MADr r1.xy, h2.xz--, const.zw--, r1.zw--;
+ | SCT1 | mov | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | TEX | txl | 32: TXLr h2, r1, const.xxxx, TEX0;
+ | SCB0/1 | add | 34: ADDh/2 h2, h0, h2;
+ | | |
+ 10 | SCT0/1 | mov | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | TEX | txl | 35: TXLr h1, g[TEX0], const.xxxx, TEX0;
+ | SCB0 | max | 37: MAXh h5.y, h5.-x--, h1.-w--;
+ | SCB1 | min | 38: MINh h4.w, h1, h5;
+ | | |
+ 11 | SCT0 | mad | 39: MADr r0.xy,-h4, const.xy--, r1.zw--;
+ | SCT1 | mov | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | TEX | txl | 41: TXLr h0, r0, const.zzzz, TEX0;
+ | SCB0 | mad | 44: MADr r2.xy, h4, const.xy--, r1.zw--;
+ | SCB1 | add | 43: ADDh*8 h5.z, h5.--y-,-h4.--w-;
+ | | |
+ 12 | SCT0/1 | mov | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | TEX | txl | 46: TXLr h3, r2, const.xxxx, TEX0;
+ | SCB0/1 | add | 48: ADDh/2 h0, h0, h3;
+ | | |
+ 13 | SCT0/1 | mad | 49: ADDh/2 h3, h0, h2;
+ | SCB0/1 | mul | 50: MOVh h0, h3;
+ | | |
+ 14 | SCT0 | set | 51: SLTh h3.x, h3.w---, h5.w---;
+ | SCT1 | set | 52: SGTh h3.w, h3, h5.---x;
+ | SCB0 | set | 54: SLThc0 rc, h5.z---, h5;
+ | SCB1 | add | 53: ADDxc0_s rc, h3.---x, h3;
+ | | |
+ 15 | SCT0/1 | mul | 55: MOVh h0(NE0.wwww), h2;
+ | SCB0/1 | mul | 56: MOVh h0(NE0.xxxx), h1;
+
+Pass SCT TEX SCB
+ 1: 0% 100% 25%
+ 2: 0% 100% 25%
+ 3: 0% 100% 50%
+ 4: 0% 100% 50%
+ 5: 50% 0% 25%
+ 6: 0% 0% 25%
+ 7: 100% 0% 25%
+ 8: 0% 100% 50%
+ 9: 0% 100% 100%
+ 10: 0% 100% 50%
+ 11: 0% 100% 75%
+ 12: 0% 100% 100%
+ 13: 100% 0% 100%
+ 14: 50% 0% 50%
+ 15: 100% 0% 100%
+
+MEAN: 26% 60% 56%
+
+Pass SCT0 SCT1 TEX SCB0 SCB1
+ 1: 0% 0% 100% 100% 0%
+ 2: 0% 0% 100% 100% 0%
+ 3: 0% 0% 100% 100% 100%
+ 4: 0% 0% 100% 100% 100%
+ 5: 100% 100% 0% 100% 0%
+ 6: 0% 0% 0% 0% 100%
+ 7: 100% 100% 0% 0% 100%
+ 8: 0% 0% 100% 100% 100%
+ 9: 0% 0% 100% 100% 100%
+ 10: 0% 0% 100% 100% 100%
+ 11: 0% 0% 100% 100% 100%
+ 12: 0% 0% 100% 100% 100%
+ 13: 100% 100% 0% 100% 100%
+ 14: 100% 100% 0% 100% 100%
+ 15: 100% 100% 0% 100% 100%
+
+MEAN: 33% 33% 60% 86% 80%
+Fragment Performance Setup: Driver RSX Compiler, GPU RSX, Flags 0x5
+Results 15 cycles, 3 r regs, 800,000,000 pixels/s
+============================================================================*/
+#if (FXAA_PS3 == 1) && (FXAA_EARLY_EXIT == 1)
+/*--------------------------------------------------------------------------*/
+#pragma disablepc all
+#pragma option O2
+#pragma option OutColorPrec=fp16
+#pragma texformat default RGBA8
+/*==========================================================================*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ sampler2D tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PS3
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+// (1)
+ half4 rgbyNe = h4tex2Dlod(tex, half4(posPos.zy, 0, 0));
+ half lumaNe = rgbyNe.w + half(1.0/512.0);
+/*--------------------------------------------------------------------------*/
+// (2)
+ half4 lumaSw = h4tex2Dlod(tex, half4(posPos.xw, 0, 0));
+ half lumaSwNegNe = lumaSw.w - lumaNe;
+/*--------------------------------------------------------------------------*/
+// (3)
+ half4 lumaNw = h4tex2Dlod(tex, half4(posPos.xy, 0, 0));
+ half lumaMaxNwSw = max(lumaNw.w, lumaSw.w);
+ half lumaMinNwSw = min(lumaNw.w, lumaSw.w);
+/*--------------------------------------------------------------------------*/
+// (4)
+ half4 lumaSe = h4tex2Dlod(tex, half4(posPos.zw, 0, 0));
+ half dirZ = lumaNw.w + lumaSwNegNe;
+ half dirX = -lumaNw.w + lumaSwNegNe;
+/*--------------------------------------------------------------------------*/
+// (5)
+ half3 dir;
+ dir.y = 0.0;
+ dir.x = lumaSe.w + dirX;
+ dir.z = -lumaSe.w + dirZ;
+ half lumaMinNeSe = min(lumaNe, lumaSe.w);
+/*--------------------------------------------------------------------------*/
+// (6)
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir).xz;
+ half dirAbsMinTimes8 = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+// (7)
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimes8, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half lumaMaxNeSe = max(lumaNe, lumaSe.w);
+/*--------------------------------------------------------------------------*/
+// (8)
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+ temp1N = h4tex2Dlod(tex, half4(temp1N.xy, 0.0, 0.0));
+ half lumaMax = max(lumaMaxNwSw, lumaMaxNeSe);
+ half lumaMin = min(lumaMinNwSw, lumaMinNeSe);
+/*--------------------------------------------------------------------------*/
+// (9)
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+ rgby1 = h4tex2Dlod(tex, half4(rgby1.xy, 0.0, 0.0));
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (10)
+ half4 rgbyM = h4tex2Dlod(tex, half4(pos.xy, 0.0, 0.0));
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+ half lumaMinM = min(lumaMin, rgbyM.w);
+/*--------------------------------------------------------------------------*/
+// (11)
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = h4tex2Dlod(tex, half4(temp2N.xy, 0.0, 0.0));
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ half lumaRangeM = (lumaMaxM - lumaMinM) / FXAA_CONSOLE__EDGE_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+// (12)
+ rgby2 = h4tex2Dlod(tex, half4(rgby2.xy, 0.0, 0.0));
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (13)
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+// (14)
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+ bool earlyExit = lumaRangeM < lumaMax;
+ bool twoTap = twoTapLt || twoTapGt;
+/*--------------------------------------------------------------------------*/
+// (15)
+ if(twoTap) rgby2 = rgby1;
+ if(earlyExit) rgby2 = rgbyM;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 CONSOLE - PC PIXEL SHADER
+
+------------------------------------------------------------------------------
+Using a modified version of the PS3 version here to best target old hardware.
+============================================================================*/
+#if (FXAA_PC_CONSOLE == 1)
+/*--------------------------------------------------------------------------*/
+half4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xy__} = upper left of pixel
+ // {__zw} = lower right of pixel
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = alpha output is junk value
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {xy} = rcpFrame not used on PC version of FXAA Console
+ float2 rcpFrame,
+ // This must be from a constant/uniform.
+ // {x___} = 2.0/screenWidthInPixels
+ // {_y__} = 2.0/screenHeightInPixels
+ // {__z_} = 0.5/screenWidthInPixels
+ // {___w} = 0.5/screenHeightInPixels
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ half4 dir;
+ dir.y = 0.0;
+ half4 lumaNe = FxaaTexTop(tex, posPos.zy);
+ lumaNe.w += half(1.0/384.0);
+ dir.x = -lumaNe.w;
+ dir.z = -lumaNe.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaSw = FxaaTexTop(tex, posPos.xw);
+ dir.x += lumaSw.w;
+ dir.z += lumaSw.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaNw = FxaaTexTop(tex, posPos.xy);
+ dir.x -= lumaNw.w;
+ dir.z += lumaNw.w;
+/*--------------------------------------------------------------------------*/
+ half4 lumaSe = FxaaTexTop(tex, posPos.zw);
+ dir.x += lumaSe.w;
+ dir.z -= lumaSe.w;
+/*==========================================================================*/
+ #if (FXAA_EARLY_EXIT == 1)
+ half4 rgbyM = FxaaTexTop(tex, pos.xy);
+/*--------------------------------------------------------------------------*/
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+/*--------------------------------------------------------------------------*/
+ half lumaMinM = min(lumaMin, rgbyM.w);
+ half lumaMaxM = max(lumaMax, rgbyM.w);
+/*--------------------------------------------------------------------------*/
+ if((lumaMaxM - lumaMinM) < max(FXAA_CONSOLE__EDGE_THRESHOLD_MIN, lumaMax * FXAA_CONSOLE__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+ #endif
+/*==========================================================================*/
+ half4 dir1_pos;
+ dir1_pos.xy = normalize(dir.xyz).xz;
+ half dirAbsMinTimesC = min(abs(dir1_pos.x), abs(dir1_pos.y)) * half(FXAA_CONSOLE__EDGE_SHARPNESS);
+/*--------------------------------------------------------------------------*/
+ half4 dir2_pos;
+ dir2_pos.xy = clamp(dir1_pos.xy / dirAbsMinTimesC, half(-2.0), half(2.0));
+ dir1_pos.zw = pos.xy;
+ dir2_pos.zw = pos.xy;
+ half4 temp1N;
+ temp1N.xy = dir1_pos.zw - dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+ temp1N = FxaaTexTop(tex, temp1N.xy);
+ half4 rgby1;
+ rgby1.xy = dir1_pos.zw + dir1_pos.xy * rcpFrameOpt.zw;
+/*--------------------------------------------------------------------------*/
+ rgby1 = FxaaTexTop(tex, rgby1.xy);
+ rgby1 = (temp1N + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+ half4 temp2N;
+ temp2N.xy = dir2_pos.zw - dir2_pos.xy * rcpFrameOpt.xy;
+ temp2N = FxaaTexTop(tex, temp2N.xy);
+/*--------------------------------------------------------------------------*/
+ half4 rgby2;
+ rgby2.xy = dir2_pos.zw + dir2_pos.xy * rcpFrameOpt.xy;
+ rgby2 = FxaaTexTop(tex, rgby2.xy);
+ rgby2 = (temp2N + rgby2) * 0.5;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_EARLY_EXIT == 0)
+ half lumaMin = min(min(lumaNw.w, lumaSw.w), min(lumaNe.w, lumaSe.w));
+ half lumaMax = max(max(lumaNw.w, lumaSw.w), max(lumaNe.w, lumaSe.w));
+ #endif
+ rgby2 = (rgby2 + rgby1) * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool twoTapLt = rgby2.w < lumaMin;
+ bool twoTapGt = rgby2.w > lumaMax;
+/*--------------------------------------------------------------------------*/
+ if(twoTapLt || twoTapGt) rgby2 = rgby1;
+/*--------------------------------------------------------------------------*/
+ return rgby2; }
+/*==========================================================================*/
+#endif
+
+
+
+/*============================================================================
+
+ FXAA3 QUALITY - PC
+
+============================================================================*/
+#if (FXAA_PC == 1)
+/*--------------------------------------------------------------------------*/
+float4 FxaaPixelShader(
+ // {xy} = center of pixel
+ float2 pos,
+ // {xyzw} = not used on FXAA3 Quality
+ float4 posPos,
+ // {rgb_} = color in linear or perceptual color space
+ // {___a} = luma in perceptual color space (not linear)
+ FxaaTex tex,
+ // This must be from a constant/uniform.
+ // {x_} = 1.0/screenWidthInPixels
+ // {_y} = 1.0/screenHeightInPixels
+ float2 rcpFrame,
+ // {xyzw} = not used on FXAA3 Quality
+ float4 rcpFrameOpt
+) {
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 1)
+ float4 luma4A = FxaaTexOffAlpha4(tex, pos.xy, FxaaInt2(-1, -1), rcpFrame.xy);
+ #if (FXAA_DISCARD == 0)
+ float4 rgbyM = FxaaTexTop(tex, pos.xy);
+ #endif
+ float4 luma4B = FxaaTexAlpha4(tex, pos.xy, rcpFrame.xy);
+ float lumaNE = FxaaTexOff(tex, pos.xy, FxaaInt2(1, -1), rcpFrame.xy).w;
+ float lumaSW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 1), rcpFrame.xy).w;
+ float lumaNW = luma4A.w;
+ float lumaN = luma4A.z;
+ float lumaW = luma4A.x;
+ float lumaM = luma4A.y;
+ float lumaE = luma4B.z;
+ float lumaS = luma4B.x;
+ float lumaSE = luma4B.y;
+ #else
+ float lumaN = FxaaTexOff(tex, pos.xy, FxaaInt2(0, -1), rcpFrame.xy).w;
+ float lumaW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 0), rcpFrame.xy).w;
+ float4 rgbyM = FxaaTexTop(tex, pos.xy);
+ float lumaE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 0), rcpFrame.xy).w;
+ float lumaS = FxaaTexOff(tex, pos.xy, FxaaInt2( 0, 1), rcpFrame.xy).w;
+ float lumaM = rgbyM.w;
+ #endif
+/*--------------------------------------------------------------------------*/
+ float rangeMin = min(lumaM, min(min(lumaN, lumaW), min(lumaS, lumaE)));
+ float rangeMax = max(lumaM, max(max(lumaN, lumaW), max(lumaS, lumaE)));
+ float range = rangeMax - rangeMin;
+/*--------------------------------------------------------------------------*/
+ if(range < max(FXAA_QUALITY__EDGE_THRESHOLD_MIN, rangeMax * FXAA_QUALITY__EDGE_THRESHOLD))
+ #if (FXAA_DISCARD == 1)
+ FxaaDiscard;
+ #else
+ return rgbyM;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_GATHER4_ALPHA == 0)
+ float lumaNW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1,-1), rcpFrame.xy).w;
+ float lumaNE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1,-1), rcpFrame.xy).w;
+ float lumaSW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1, 1), rcpFrame.xy).w;
+ float lumaSE = FxaaTexOff(tex, pos.xy, FxaaInt2( 1, 1), rcpFrame.xy).w;
+ #endif
+/*--------------------------------------------------------------------------*/
+ #define FXAA_QUALITY__SUBPIX_TRIM_SCALE (1.0/(1.0 - FXAA_QUALITY__SUBPIX_TRIM))
+/*--------------------------------------------------------------------------*/
+ float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25;
+ float rangeL = abs(lumaL - lumaM);
+ float blendL = FxaaSat((rangeL / range) - FXAA_QUALITY__SUBPIX_TRIM) * FXAA_QUALITY__SUBPIX_TRIM_SCALE;
+ blendL = min(FXAA_QUALITY__SUBPIX_CAP, blendL);
+/*--------------------------------------------------------------------------*/
+ float edgeVert =
+ abs(lumaNW + (-2.0 * lumaN) + lumaNE) +
+ 2.0 * abs(lumaW + (-2.0 * lumaM) + lumaE ) +
+ abs(lumaSW + (-2.0 * lumaS) + lumaSE);
+ float edgeHorz =
+ abs(lumaNW + (-2.0 * lumaW) + lumaSW) +
+ 2.0 * abs(lumaN + (-2.0 * lumaM) + lumaS ) +
+ abs(lumaNE + (-2.0 * lumaE) + lumaSE);
+ bool horzSpan = edgeHorz >= edgeVert;
+/*--------------------------------------------------------------------------*/
+ float lengthSign = horzSpan ? -rcpFrame.y : -rcpFrame.x;
+ if(!horzSpan) lumaN = lumaW;
+ if(!horzSpan) lumaS = lumaE;
+ float gradientN = abs(lumaN - lumaM);
+ float gradientS = abs(lumaS - lumaM);
+ lumaN = (lumaN + lumaM) * 0.5;
+ lumaS = (lumaS + lumaM) * 0.5;
+/*--------------------------------------------------------------------------*/
+ bool pairN = gradientN >= gradientS;
+ if(!pairN) lumaN = lumaS;
+ if(!pairN) gradientN = gradientS;
+ if(!pairN) lengthSign *= -1.0;
+ float2 posN;
+ posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5);
+ posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0);
+/*--------------------------------------------------------------------------*/
+ #define FXAA_SEARCH_STEPS 6
+ #define FXAA_SEARCH_THRESHOLD (1.0/4.0)
+/*--------------------------------------------------------------------------*/
+ gradientN *= FXAA_SEARCH_THRESHOLD;
+/*--------------------------------------------------------------------------*/
+ float2 posP = posN;
+ float2 offNP = horzSpan ?
+ FxaaFloat2(rcpFrame.x, 0.0) :
+ FxaaFloat2(0.0, rcpFrame.y);
+ float lumaEndN;
+ float lumaEndP;
+ bool doneN = false;
+ bool doneP = false;
+ posN += offNP * (-1.5);
+ posP += offNP * ( 1.5);
+ for(int i = 0; i < FXAA_SEARCH_STEPS; i++) {
+ lumaEndN = FxaaTexTop(tex, posN.xy).w;
+ lumaEndP = FxaaTexTop(tex, posP.xy).w;
+ bool doneN2 = abs(lumaEndN - lumaN) >= gradientN;
+ bool doneP2 = abs(lumaEndP - lumaN) >= gradientN;
+ if(doneN2 && !doneN) posN += offNP;
+ if(doneP2 && !doneP) posP -= offNP;
+ if(doneN2 && doneP2) break;
+ doneN = doneN2;
+ doneP = doneP2;
+ if(!doneN) posN -= offNP * 2.0;
+ if(!doneP) posP += offNP * 2.0; }
+/*--------------------------------------------------------------------------*/
+ float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y;
+ float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y;
+/*--------------------------------------------------------------------------*/
+ bool directionN = dstN < dstP;
+ lumaEndN = directionN ? lumaEndN : lumaEndP;
+/*--------------------------------------------------------------------------*/
+ if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0))
+ lengthSign = 0.0;
+/*--------------------------------------------------------------------------*/
+ float spanLength = (dstP + dstN);
+ dstN = directionN ? dstN : dstP;
+ float subPixelOffset = 0.5 + (dstN * (-1.0/spanLength));
+ subPixelOffset += blendL * (1.0/8.0);
+ subPixelOffset *= lengthSign;
+ float3 rgbF = FxaaTexTop(tex, FxaaFloat2(
+ pos.x + (horzSpan ? 0.0 : subPixelOffset),
+ pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz;
+/*--------------------------------------------------------------------------*/
+ #if (FXAA_LINEAR == 1)
+ lumaL *= lumaL;
+ #endif
+ float lumaF = dot(rgbF, float3(0.299, 0.587, 0.114)) + (1.0/(65536.0*256.0));
+ float lumaB = FxaaLerp(lumaF, lumaL, blendL);
+ float scale = min(4.0, lumaB/lumaF);
+ rgbF *= scale;
+ return float4(rgbF, lumaM); }
+/*==========================================================================*/
+#endif
+
+
+
diff --git a/res/effectlib/SMAA.glsllib b/res/effectlib/SMAA.glsllib
new file mode 100644
index 0000000..97e0153
--- /dev/null
+++ b/res/effectlib/SMAA.glsllib
@@ -0,0 +1,1444 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/**
+ * Copyright (C) 2011 Jorge Jimenez (jorge@iryoku.com)
+ * Copyright (C) 2011 Jose I. Echevarria (joseignacioechevarria@gmail.com)
+ * Copyright (C) 2011 Belen Masia (bmasia@unizar.es)
+ * Copyright (C) 2011 Fernando Navarro (fernandn@microsoft.com)
+ * Copyright (C) 2011 Diego Gutierrez (diegog@unizar.es)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution:
+ *
+ * "Uses SMAA. Copyright (C) 2011 by Jorge Jimenez, Jose I. Echevarria,
+ * Tiago Sousa, Belen Masia, Fernando Navarro and Diego Gutierrez."
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
+ * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the copyright holders.
+ */
+
+
+/**
+ * _______ ___ ___ ___ ___
+ * / || \/ | / \ / \
+ * | (---- | \ / | / ^ \ / ^ \
+ * \ \ | |\/| | / /_\ \ / /_\ \
+ * ----) | | | | | / _____ \ / _____ \
+ * |_______/ |__| |__| /__/ \__\ /__/ \__\
+ *
+ * E N H A N C E D
+ * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G
+ *
+ * http://www.iryoku.com/smaa/
+ *
+ * Hi, welcome aboard!
+ *
+ * Here you'll find instructions to get the shader up and running as fast as
+ * possible.
+ *
+ * IMPORTANTE NOTICE: when updating, remember to update both this file and the
+ * precomputed textures! They may change from version to version.
+ *
+ * The shader has three passes, chained together as follows:
+ *
+ * |input|------------------
+ * v |
+ * [ SMAA*EdgeDetection ] |
+ * v |
+ * |edgesTex| |
+ * v |
+ * [ SMAABlendingWeightCalculation ] |
+ * v |
+ * |blendTex| |
+ * v |
+ * [ SMAANeighborhoodBlending ] <------
+ * v
+ * |output|
+ *
+ * Note that each [pass] has its own vertex and pixel shader.
+ *
+ * You've three edge detection methods to choose from: luma, color or depth.
+ * They represent different quality/performance and anti-aliasing/sharpness
+ * tradeoffs, so our recommendation is for you to choose the one that best
+ * suits your particular scenario:
+ *
+ * - Depth edge detection is usually the fastest but it may miss some edges.
+ *
+ * - Luma edge detection is usually more expensive than depth edge detection,
+ * but catches visible edges that depth edge detection can miss.
+ *
+ * - Color edge detection is usually the most expensive one but catches
+ * chroma-only edges.
+ *
+ * For quickstarters: just use luma edge detection.
+ *
+ * The general advice is to not rush the integration process and ensure each
+ * step is done correctly (don't try to integrate SMAA T2x with predicated edge
+ * detection from the start!). Ok then, let's go!
+ *
+ * 1. The first step is to create two RGBA temporal framebuffers for holding
+ * |edgesTex| and |blendTex|.
+ *
+ * In DX10, you can use a RG framebuffer for the edges texture, but in our
+ * experience it yields worse performance.
+ *
+ * On the Xbox 360, you can use the same framebuffer for resolving both
+ * |edgesTex| and |blendTex|, as they aren't needed simultaneously.
+ *
+ * 2. Both temporal framebuffers |edgesTex| and |blendTex| must be cleared
+ * each frame. Do not forget to clear the alpha channel!
+ *
+ * 3. The next step is loading the two supporting precalculated textures,
+ * 'areaTex' and 'searchTex'. You'll find them in the 'Textures' folder as
+ * C++ headers, and also as regular DDS files. They'll be needed for the
+ * 'SMAABlendingWeightCalculation' pass.
+ *
+ * If you use the C++ headers, be sure to load them in the format specified
+ * inside of them.
+ *
+ * 4. In DX9, all samplers must be set to linear filtering and clamp, with the
+ * exception of 'searchTex', which must be set to point filtering.
+ *
+ * 5. All texture reads and buffer writes must be non-sRGB, with the exception
+ * of the input read and the output write of input in
+ * 'SMAANeighborhoodBlending' (and only in this pass!). If sRGB reads in
+ * this last pass are not possible, the technique will work anyway, but
+ * will perform antialiasing in gamma space.
+ *
+ * IMPORTANT: for best results the input read for the color/luma edge
+ * detection should *NOT* be sRGB.
+ *
+ * 6. Before including SMAA.h you'll have to setup the framebuffer pixel size,
+ * the target and any optional configuration defines. Optionally you can
+ * use a preset.
+ *
+ * You have three targets available:
+ * SMAA_HLSL_3
+ * SMAA_HLSL_4
+ * SMAA_HLSL_4_1
+ * SMAA_GLSL_3 *
+ * SMAA_GLSL_4 *
+ *
+ * * (See SMAA_ONLY_COMPILE_VS below).
+ *
+ * And four presets:
+ * SMAA_PRESET_LOW (%60 of the quality)
+ * SMAA_PRESET_MEDIUM (%80 of the quality)
+ * SMAA_PRESET_HIGH (%95 of the quality)
+ * SMAA_PRESET_ULTRA (%99 of the quality)
+ *
+ * For example:
+ * #define SMAA_PIXEL_SIZE float2(1.0 / 1280.0, 1.0 / 720.0)
+ * #define SMAA_HLSL_4 1
+ * #define SMAA_PRESET_HIGH 1
+ * include "SMAA.h"
+ *
+ * 7. Then, you'll have to setup the passes as indicated in the scheme above.
+ * You can take a look into SMAA.fx, to see how we did it for our demo.
+ * Checkout the function wrappers, you may want to copy-paste them!
+ *
+ * 8. It's recommended to validate the produced |edgesTex| and |blendTex|.
+ * It's advised to not continue with the implementation until both buffers
+ * are verified to produce identical results to our reference demo.
+ *
+ * 9. After you get the last pass to work, it's time to optimize. You'll have
+ * to initialize a stencil buffer in the first pass (discard is already in
+ * the code), then mask execution by using it the second pass. The last
+ * pass should be executed in all pixels.
+ *
+ *
+ * After this point you can choose to enable predicated thresholding,
+ * temporal supersampling and motion blur integration:
+ *
+ * a) If you want to use predicated thresholding, take a look into
+ * SMAA_PREDICATION; you'll need to pass an extra texture in the edge
+ * detection pass.
+ *
+ * b) If you want to enable temporal supersampling (SMAA T2x):
+ *
+ * 1. The first step is to render using subpixel jitters. I won't go into
+ * detail, but it's as simple as moving each vertex position in the
+ * vertex shader, you can check how we do it in our DX10 demo.
+ *
+ * 2. Then, you must setup the temporal resolve. You may want to take a look
+ * into SMAAResolve for resolving 2x modes. After you get it working, you'll
+ * probably see ghosting everywhere. But fear not, you can enable the
+ * CryENGINE temporal reprojection by setting the SMAA_REPROJECTION macro.
+ *
+ * 3. The next step is to apply SMAA to each subpixel jittered frame, just as
+ * done for 1x.
+ *
+ * 4. At this point you should already have something usable, but for best
+ * results the proper area textures must be set depending on current jitter.
+ * For this, the parameter 'subsampleIndices' of
+ * 'SMAABlendingWeightCalculationPS' must be set as follows, for our T2x
+ * mode:
+ *
+ * @SUBSAMPLE_INDICES
+ *
+ * | S# | Camera Jitter | subsampleIndices |
+ * +----+------------------+--------------------+
+ * | 0 | ( 0.25, -0.25) | int4(1, 1, 1, 0) |
+ * | 1 | (-0.25, 0.25) | int4(2, 2, 2, 0) |
+ *
+ * These jitter positions assume a bottom-to-top y axis. S# stands for the
+ * sample number.
+ *
+ * More information about temporal supersampling here:
+ * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf
+ *
+ * c) If you want to enable spatial multisampling (SMAA S2x):
+ *
+ * 1. The scene must be rendered using MSAA 2x. The MSAA 2x buffer must be
+ * created with:
+ * - DX10: see below (*)
+ * - DX10.1: D3D10_STANDARD_MULTISAMPLE_PATTERN or
+ * - DX11: D3D11_STANDARD_MULTISAMPLE_PATTERN
+ *
+ * This allows to ensure that the subsample order matches the table in
+ * @SUBSAMPLE_INDICES.
+ *
+ * (*) In the case of DX10, we refer the reader to:
+ * - SMAA::detectMSAAOrder and
+ * - SMAA::msaaReorder
+ *
+ * These functions allow to match the standard multisample patterns by
+ * detecting the subsample order for a specific GPU, and reordering
+ * them appropriately.
+ *
+ * 2. A shader must be run to output each subsample into a separate buffer
+ * (DX10 is required). You can use SMAASeparate for this purpose, or just do
+ * it in an existing pass (for example, in the tone mapping pass).
+ *
+ * 3. The full SMAA 1x pipeline must be run for each separated buffer, storing
+ * the results in the final buffer. The second run should alpha blend with
+ * the existing final buffer using a blending factor of 0.5.
+ * 'subsampleIndices' must be adjusted as in the SMAA T2x case (see point
+ * b).
+ *
+ * d) If you want to enable temporal supersampling on top of SMAA S2x
+ * (which actually is SMAA 4x):
+ *
+ * 1. SMAA 4x consists on temporally jittering SMAA S2x, so the first step is
+ * to calculate SMAA S2x for current frame. In this case, 'subsampleIndices'
+ * must be set as follows:
+ *
+ * | F# | S# | Camera Jitter | Net Jitter | subsampleIndices |
+ * +----+----+--------------------+-------------------+--------------------+
+ * | 0 | 0 | ( 0.125, 0.125) | ( 0.375, -0.125) | int4(5, 3, 1, 3) |
+ * | 0 | 1 | ( 0.125, 0.125) | (-0.125, 0.375) | int4(4, 6, 2, 3) |
+ * +----+----+--------------------+-------------------+--------------------+
+ * | 1 | 2 | (-0.125, -0.125) | ( 0.125, -0.375) | int4(3, 5, 1, 4) |
+ * | 1 | 3 | (-0.125, -0.125) | (-0.375, 0.125) | int4(6, 4, 2, 4) |
+ *
+ * These jitter positions assume a bottom-to-top y axis. F# stands for the
+ * frame number. S# stands for the sample number.
+ *
+ * 2. After calculating SMAA S2x for current frame (with the new subsample
+ * indices), previous frame must be reprojected as in SMAA T2x mode (see
+ * point b).
+ *
+ * e) If motion blur is used, you may want to do the edge detection pass
+ * together with motion blur. This has two advantages:
+ *
+ * 1. Pixels under heavy motion can be omitted from the edge detection process.
+ * For these pixels we can just store "no edge", as motion blur will take
+ * care of them.
+ * 2. The center pixel tap is reused.
+ *
+ * Note that in this case depth testing should be used instead of stenciling,
+ * as we have to write all the pixels in the motion blur pass.
+ *
+ * That's it!
+ */
+
+//-----------------------------------------------------------------------------
+// SMAA Presets
+
+/**
+ * Note that if you use one of these presets, the corresponding macros below
+ * won't be used.
+ */
+
+#if SMAA_PRESET_LOW == 1
+#define SMAA_THRESHOLD 0.15
+#define SMAA_MAX_SEARCH_STEPS 4
+#define SMAA_MAX_SEARCH_STEPS_DIAG 0
+#define SMAA_CORNER_ROUNDING 100
+#elif SMAA_PRESET_MEDIUM == 1
+#define SMAA_THRESHOLD 0.1
+#define SMAA_MAX_SEARCH_STEPS 8
+#define SMAA_MAX_SEARCH_STEPS_DIAG 0
+#define SMAA_CORNER_ROUNDING 100
+#elif SMAA_PRESET_HIGH == 1
+#define SMAA_THRESHOLD 0.1
+#define SMAA_MAX_SEARCH_STEPS 16
+#define SMAA_MAX_SEARCH_STEPS_DIAG 8
+#define SMAA_CORNER_ROUNDING 25
+#elif SMAA_PRESET_ULTRA == 1
+#define SMAA_THRESHOLD 0.05
+#define SMAA_MAX_SEARCH_STEPS 32
+#define SMAA_MAX_SEARCH_STEPS_DIAG 16
+#define SMAA_CORNER_ROUNDING 25
+#endif
+
+//-----------------------------------------------------------------------------
+// Configurable Defines
+
+/**
+ * SMAA_THRESHOLD specifies the threshold or sensitivity to edges.
+ * Lowering this value you will be able to detect more edges at the expense of
+ * performance.
+ *
+ * Range: [0, 0.5]
+ * 0.1 is a reasonable value, and allows to catch most visible edges.
+ * 0.05 is a rather overkill value, that allows to catch 'em all.
+ *
+ * If temporal supersampling is used, 0.2 could be a reasonable value, as low
+ * contrast edges are properly filtered by just 2x.
+ */
+#ifndef SMAA_THRESHOLD
+#define SMAA_THRESHOLD 0.1
+#endif
+
+/**
+ * SMAA_DEPTH_THRESHOLD specifies the threshold for depth edge detection.
+ *
+ * Range: depends on the depth range of the scene.
+ */
+#ifndef SMAA_DEPTH_THRESHOLD
+#define SMAA_DEPTH_THRESHOLD (0.1 * SMAA_THRESHOLD)
+#endif
+
+/**
+ * SMAA_MAX_SEARCH_STEPS specifies the maximum steps performed in the
+ * horizontal/vertical pattern searches, at each side of the pixel.
+ *
+ * In number of pixels, it's actually the double. So the maximum line length
+ * perfectly handled by, for example 16, is 64 (by perfectly, we meant that
+ * longer lines won't look as good, but still antialiased).
+ *
+ * Range: [0, 98]
+ */
+#ifndef SMAA_MAX_SEARCH_STEPS
+#define SMAA_MAX_SEARCH_STEPS 16
+#endif
+
+/**
+ * SMAA_MAX_SEARCH_STEPS_DIAG specifies the maximum steps performed in the
+ * diagonal pattern searches, at each side of the pixel. In this case we jump
+ * one pixel at time, instead of two.
+ *
+ * Range: [0, 20]; set it to 0 to disable diagonal processing.
+ *
+ * On high-end machines it is cheap (between a 0.8x and 0.9x slower for 16
+ * steps), but it can have a significant impact on older machines.
+ */
+#ifndef SMAA_MAX_SEARCH_STEPS_DIAG
+#define SMAA_MAX_SEARCH_STEPS_DIAG 8
+#endif
+
+/**
+ * SMAA_CORNER_ROUNDING specifies how much sharp corners will be rounded.
+ *
+ * Range: [0, 100]; set it to 100 to disable corner detection.
+ */
+#ifndef SMAA_CORNER_ROUNDING
+#define SMAA_CORNER_ROUNDING 25
+#endif
+
+/**
+ * Predicated thresholding allows to better preserve texture details and to
+ * improve performance, by decreasing the number of detected edges using an
+ * additional buffer like the light accumulation buffer, object ids or even the
+ * depth buffer (the depth buffer usage may be limited to indoor or short range
+ * scenes).
+ *
+ * It locally decreases the luma or color threshold if an edge is found in an
+ * additional buffer (so the global threshold can be higher).
+ *
+ * This method was developed by Playstation EDGE MLAA team, and used in
+ * Killzone 3, by using the light accumulation buffer. More information here:
+ * http://iryoku.com/aacourse/downloads/06-MLAA-on-PS3.pptx
+ */
+#ifndef SMAA_PREDICATION
+#define SMAA_PREDICATION 0
+#endif
+
+/**
+ * Threshold to be used in the additional predication buffer.
+ *
+ * Range: depends on the input, so you'll have to find the magic number that
+ * works for you.
+ */
+#ifndef SMAA_PREDICATION_THRESHOLD
+#define SMAA_PREDICATION_THRESHOLD 0.01
+#endif
+
+/**
+ * How much to scale the global threshold used for luma or color edge
+ * detection when using predication.
+ *
+ * Range: [1, 5]
+ */
+#ifndef SMAA_PREDICATION_SCALE
+#define SMAA_PREDICATION_SCALE 2.0
+#endif
+
+/**
+ * How much to locally decrease the threshold.
+ *
+ * Range: [0, 1]
+ */
+#ifndef SMAA_PREDICATION_STRENGTH
+#define SMAA_PREDICATION_STRENGTH 0.4
+#endif
+
+/**
+ * Temporal reprojection allows to remove ghosting artifacts when using
+ * temporal supersampling. We use the CryEngine 3 method which also introduces
+ * velocity weighting. This feature is of extreme importance for totally
+ * removing ghosting. More information here:
+ * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf
+ *
+ * Note that you'll need to setup a velocity buffer for enabling reprojection.
+ * For static geometry, saving the previous depth buffer is a viable
+ * alternative.
+ */
+#ifndef SMAA_REPROJECTION
+#define SMAA_REPROJECTION 0
+#endif
+
+/**
+ * SMAA_REPROJECTION_WEIGHT_SCALE controls the velocity weighting. It allows to
+ * remove ghosting trails behind the moving object, which are not removed by
+ * just using reprojection. Using low values will exhibit ghosting, while using
+ * high values will disable temporal supersampling under motion.
+ *
+ * Behind the scenes, velocity weighting removes temporal supersampling when
+ * the velocity of the subsamples differs (meaning they are different objects).
+ *
+ * Range: [0, 80]
+ */
+#define SMAA_REPROJECTION_WEIGHT_SCALE 30.0
+
+/**
+ * In the last pass we leverage bilinear filtering to avoid some lerps.
+ * However, bilinear filtering is done in gamma space in DX9, under DX9
+ * hardware (but not in DX9 code running on DX10 hardware), which gives
+ * inaccurate results.
+ *
+ * So, if you are in DX9, under DX9 hardware, and do you want accurate linear
+ * blending, you must set this flag to 1.
+ *
+ * It's ignored when using SMAA_HLSL_4, and of course, only has sense when
+ * using sRGB read and writes on the last pass.
+ */
+#ifndef SMAA_DIRECTX9_LINEAR_BLEND
+#define SMAA_DIRECTX9_LINEAR_BLEND 0
+#endif
+
+/**
+ * On ATI compilers, discard cannot be used in vertex shaders. Thus, they need
+ * to be compiled separately. These macros allow to easily accomplish it.
+ */
+#ifndef SMAA_ONLY_COMPILE_VS
+#define SMAA_ONLY_COMPILE_VS 0
+#endif
+#ifndef SMAA_ONLY_COMPILE_PS
+#define SMAA_ONLY_COMPILE_PS 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Non-Configurable Defines
+
+#ifndef SMAA_AREATEX_MAX_DISTANCE
+#define SMAA_AREATEX_MAX_DISTANCE 16
+#endif
+#ifndef SMAA_AREATEX_MAX_DISTANCE_DIAG
+#define SMAA_AREATEX_MAX_DISTANCE_DIAG 20
+#endif
+#define SMAA_AREATEX_PIXEL_SIZE (1.0 / float2(160.0, 560.0))
+#define SMAA_AREATEX_SUBTEX_SIZE (1.0 / 7.0)
+
+//-----------------------------------------------------------------------------
+// Porting Functions
+
+#if SMAA_HLSL_3 == 1
+#define SMAATexture2D sampler2D
+#define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
+#define SMAASampleLevelZeroPoint(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0))
+#define SMAASample(tex, coord) tex2D(tex, coord)
+#define SMAASamplePoint(tex, coord) tex2D(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlod(tex, float4(coord + offset * SMAA_PIXEL_SIZE, 0.0, 0.0))
+#define SMAASampleOffset(tex, coord, offset) tex2D(tex, coord + offset * SMAA_PIXEL_SIZE)
+#define SMAALerp(a, b, t) lerp(a, b, t)
+#define SMAASaturate(a) saturate(a)
+#define SMAAMad(a, b, c) mad(a, b, c)
+#define SMAA_FLATTEN [flatten]
+#define SMAA_BRANCH [branch]
+#endif
+#if SMAA_HLSL_4 == 1 || SMAA_HLSL_4_1 == 1
+SamplerState LinearSampler { Filter = MIN_MAG_LINEAR_MIP_POINT; AddressU = Clamp; AddressV = Clamp; };
+SamplerState PointSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; AddressV = Clamp; };
+#define SMAATexture2D Texture2D
+#define SMAASampleLevelZero(tex, coord) tex.SampleLevel(LinearSampler, coord, 0)
+#define SMAASampleLevelZeroPoint(tex, coord) tex.SampleLevel(PointSampler, coord, 0)
+#define SMAASample(tex, coord) SMAASampleLevelZero(tex, coord)
+#define SMAASamplePoint(tex, coord) SMAASampleLevelZeroPoint(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) tex.SampleLevel(LinearSampler, coord, 0, offset)
+#define SMAASampleOffset(tex, coord, offset) SMAASampleLevelZeroOffset(tex, coord, offset)
+#define SMAALerp(a, b, t) lerp(a, b, t)
+#define SMAASaturate(a) saturate(a)
+#define SMAAMad(a, b, c) mad(a, b, c)
+#define SMAA_FLATTEN [flatten]
+#define SMAA_BRANCH [branch]
+#define SMAATexture2DMS2 Texture2DMS<float4, 2>
+#define SMAALoad(tex, pos, sample) tex.Load(pos, sample)
+#endif
+#if SMAA_HLSL_4_1 == 1
+#define SMAAGather(tex, coord) tex.Gather(LinearSampler, coord, 0)
+#endif
+#if SMAA_GLSL_3 == 1 || SMAA_GLSL_4 == 1
+#define SMAATexture2D sampler2D
+#define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0)
+#define SMAASampleLevelZeroPoint(tex, coord) textureLod(tex, coord, 0.0)
+#define SMAASample(tex, coord) texture(tex, coord)
+#define SMAASamplePoint(tex, coord) texture(tex, coord)
+#define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset)
+#define SMAASampleOffset(tex, coord, offset) texture(tex, coord, offset)
+#define SMAALerp(a, b, t) mix(a, b, t)
+#define SMAASaturate(a) clamp(a, 0.0, 1.0)
+#define SMAA_FLATTEN
+#define SMAA_BRANCH
+#define float2 vec2
+#define float3 vec3
+#define float4 vec4
+#define int2 ivec2
+#define int3 ivec3
+#define int4 ivec4
+#endif
+#if SMAA_GLSL_3 == 1
+#define SMAAMad(a, b, c) (a * b + c)
+#endif
+#if SMAA_GLSL_4 == 1
+#define SMAAMad(a, b, c) fma(a, b, c)
+#define SMAAGather(tex, coord) textureGather(tex, coord)
+#endif
+
+//-----------------------------------------------------------------------------
+// Misc functions
+
+/**
+ * Gathers current pixel, and the top-left neighbors.
+ */
+float3 SMAAGatherNeighbors(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D tex) {
+ #if SMAA_HLSL_4_1 == 1 || SMAA_GLSL_4 == 1
+ return SMAAGather(tex, texcoord + SMAA_PIXEL_SIZE * float2(-0.5, -0.5)).grb;
+ #else
+ float P = SMAASample(tex, texcoord).r;
+ float Pleft = SMAASample(tex, offset[0].xy).r;
+ float Ptop = SMAASample(tex, offset[0].zw).r;
+ return float3(P, Pleft, Ptop);
+ #endif
+}
+
+/**
+ * Adjusts the threshold by means of predication.
+ */
+float2 SMAACalculatePredicatedThreshold(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex,
+ SMAATexture2D predicationTex) {
+ float3 neighbors = SMAAGatherNeighbors(texcoord, offset, predicationTex);
+ float2 delta = abs(neighbors.xx - neighbors.yz);
+ float2 edges = step(SMAA_PREDICATION_THRESHOLD, delta);
+ return SMAA_PREDICATION_SCALE * SMAA_THRESHOLD * (1.0 - SMAA_PREDICATION_STRENGTH * edges);
+}
+
+#if SMAA_ONLY_COMPILE_PS == 0
+//-----------------------------------------------------------------------------
+// Vertex Shaders
+
+/**
+ * Edge Detection Vertex Shader
+ */
+void SMAAEdgeDetectionVS(float4 position,
+ out float4 svPosition,
+ in float2 texcoord,
+ out float4 offset[3]) {
+ svPosition = position;
+
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-1.0, 0.0, 0.0, -1.0);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4( 1.0, 0.0, 0.0, 1.0);
+ offset[2] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-2.0, 0.0, 0.0, -2.0);
+}
+
+/**
+ * Blend Weight Calculation Vertex Shader
+ */
+void SMAABlendingWeightCalculationVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord,
+ out float2 pixcoord,
+ out float4 offset[3]) {
+ svPosition = position;
+
+ pixcoord = texcoord / SMAA_PIXEL_SIZE;
+
+ // We will use these offsets for the searches later on (see @PSEUDO_GATHER4):
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-0.25, -0.125, 1.25, -0.125);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-0.125, -0.25, -0.125, 1.25);
+
+ // And these for the searches, they indicate the ends of the loops:
+ offset[2] = float4(offset[0].xz, offset[1].yw) +
+ float4(-2.0, 2.0, -2.0, 2.0) *
+ SMAA_PIXEL_SIZE.xxyy * float(SMAA_MAX_SEARCH_STEPS);
+}
+
+/**
+ * Neighborhood Blending Vertex Shader
+ */
+void SMAANeighborhoodBlendingVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord,
+ out float4 offset[2]) {
+ svPosition = position;
+
+ offset[0] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4(-1.0, 0.0, 0.0, -1.0);
+ offset[1] = texcoord.xyxy + SMAA_PIXEL_SIZE.xyxy * float4( 1.0, 0.0, 0.0, 1.0);
+}
+
+/**
+ * Resolve Vertex Shader
+ */
+void SMAAResolveVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord) {
+ svPosition = position;
+}
+
+/**
+ * Separate Vertex Shader
+ */
+void SMAASeparateVS(float4 position,
+ out float4 svPosition,
+ inout float2 texcoord) {
+ svPosition = position;
+}
+#endif // SMAA_ONLY_COMPILE_PS == 0
+
+#if SMAA_ONLY_COMPILE_VS == 0
+//-----------------------------------------------------------------------------
+// Edge Detection Pixel Shaders (First Pass)
+
+/**
+ * Luma Edge Detection
+ *
+ * IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and
+ * thus 'colorTex' should be a non-sRGB texture.
+ */
+float4 SMAALumaEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate lumas:
+ float3 weights = float3(0.2126, 0.7152, 0.0722);
+ float L = dot(SMAASample(colorTex, texcoord).rgb, weights);
+ float Lleft = dot(SMAASample(colorTex, offset[0].xy).rgb, weights);
+ float Ltop = dot(SMAASample(colorTex, offset[0].zw).rgb, weights);
+
+ // We do the usual threshold:
+ float4 delta;
+ delta.xy = abs(L - float2(Lleft, Ltop));
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float Lright = dot(SMAASample(colorTex, offset[1].xy).rgb, weights);
+ float Lbottom = dot(SMAASample(colorTex, offset[1].zw).rgb, weights);
+ delta.zw = abs(L - float2(Lright, Lbottom));
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float2 maxDelta = max(delta.xy, delta.zw);
+ maxDelta = max(maxDelta.xx, maxDelta.yy);
+
+ // Calculate left-left and top-top deltas:
+ float Lleftleft = dot(SMAASample(colorTex, offset[2].xy).rgb, weights);
+ float Ltoptop = dot(SMAASample(colorTex, offset[2].zw).rgb, weights);
+ delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
+
+ // Calculate the final maximum delta:
+ maxDelta = max(maxDelta.xy, delta.zw);
+
+ /**
+ * Each edge with a delta in luma of less than 50% of the maximum luma
+ * surrounding this pixel is discarded. This allows to eliminate spurious
+ * crossing edges, and is based on the fact that, if there is too much
+ * contrast in a direction, that will hide contrast in the other
+ * neighbors.
+ * This is done after the discard intentionally as this situation doesn't
+ * happen too frequently (but it's important to do as it prevents some
+ * edges from going undetected).
+ */
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+/**
+ * Color Edge Detection
+ *
+ * IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and
+ * thus 'colorTex' should be a non-sRGB texture.
+ */
+float4 SMAAColorEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate color deltas:
+ float4 delta;
+ float3 C = SMAASample(colorTex, texcoord).rgb;
+
+ float3 Cleft = SMAASample(colorTex, offset[0].xy).rgb;
+ float3 t = abs(C - Cleft);
+ delta.x = max(max(t.r, t.g), t.b);
+
+ float3 Ctop = SMAASample(colorTex, offset[0].zw).rgb;
+ t = abs(C - Ctop);
+ delta.y = max(max(t.r, t.g), t.b);
+
+ // We do the usual threshold:
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float3 Cright = SMAASample(colorTex, offset[1].xy).rgb;
+ t = abs(C - Cright);
+ delta.z = max(max(t.r, t.g), t.b);
+
+ float3 Cbottom = SMAASample(colorTex, offset[1].zw).rgb;
+ t = abs(C - Cbottom);
+ delta.w = max(max(t.r, t.g), t.b);
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float maxDelta = max(max(max(delta.x, delta.y), delta.z), delta.w);
+
+ // Calculate left-left and top-top deltas:
+ float3 Cleftleft = SMAASample(colorTex, offset[2].xy).rgb;
+ t = abs(C - Cleftleft);
+ delta.z = max(max(t.r, t.g), t.b);
+
+ float3 Ctoptop = SMAASample(colorTex, offset[2].zw).rgb;
+ t = abs(C - Ctoptop);
+ delta.w = max(max(t.r, t.g), t.b);
+
+ // Calculate the final maximum delta:
+ maxDelta = max(max(maxDelta, delta.z), delta.w);
+
+ // Local contrast adaptation in action:
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+float4 SMAASingleChannelEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D colorTex
+ #if SMAA_PREDICATION == 1
+ , SMAATexture2D predicationTex
+ #endif
+ ) {
+ // Calculate the threshold:
+ #if SMAA_PREDICATION == 1
+ float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, colorTex, predicationTex);
+ #else
+ float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD);
+ #endif
+
+ // Calculate lumas:
+ float L = SMAASample(colorTex, texcoord).r;
+ float Lleft = SMAASample(colorTex, offset[0].xy).r;
+ float Ltop = SMAASample(colorTex, offset[0].zw).r;
+
+ // We do the usual threshold:
+ float4 delta;
+ delta.xy = abs(L - float2(Lleft, Ltop));
+ float2 edges = step(threshold, delta.xy);
+
+ // Then discard if there is no edge:
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ // Calculate right and bottom deltas:
+ float Lright = SMAASample(colorTex, offset[1].xy).r;
+ float Lbottom = SMAASample(colorTex, offset[1].zw).r;
+ delta.zw = abs(L - float2(Lright, Lbottom));
+
+ // Calculate the maximum delta in the direct neighborhood:
+ float2 maxDelta = max(delta.xy, delta.zw);
+ maxDelta = max(maxDelta.xx, maxDelta.yy);
+
+ // Calculate left-left and top-top deltas:
+ float Lleftleft = SMAASample(colorTex, offset[2].xy).r;
+ float Ltoptop = SMAASample(colorTex, offset[2].zw).r;
+ delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop));
+
+ // Calculate the final maximum delta:
+ maxDelta = max(maxDelta.xy, delta.zw);
+
+ /**
+ * Each edge with a delta in luma of less than 50% of the maximum luma
+ * surrounding this pixel is discarded. This allows to eliminate spurious
+ * crossing edges, and is based on the fact that, if there is too much
+ * contrast in a direction, that will hide contrast in the other
+ * neighbors.
+ * This is done after the discard intentionally as this situation doesn't
+ * happen too frequently (but it's important to do as it prevents some
+ * edges from going undetected).
+ */
+ edges.xy *= step(0.5 * maxDelta, delta.xy);
+
+ return float4(edges, 0.0, 0.0);
+}
+
+/**
+ * Depth Edge Detection
+ */
+float4 SMAADepthEdgeDetectionPS(float2 texcoord,
+ float4 offset[3],
+ SMAATexture2D depthTex) {
+ float3 neighbors = SMAAGatherNeighbors(texcoord, offset, depthTex);
+ float2 delta = abs(neighbors.xx - float2(neighbors.y, neighbors.z));
+ float2 edges = step(SMAA_DEPTH_THRESHOLD, delta);
+
+ if (dot(edges, float2(1.0, 1.0)) == 0.0)
+ discard;
+
+ return float4(edges, 0.0, 0.0);
+}
+
+//-----------------------------------------------------------------------------
+// Diagonal Search Functions
+
+#if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+
+/**
+ * These functions allows to perform diagonal pattern searches.
+ */
+float SMAASearchDiag1(SMAATexture2D edgesTex, float2 texcoord, float2 dir, float c) {
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ float2 e = float2(0.0, 0.0);
+ float i;
+ for (i = 0.0; i < float(SMAA_MAX_SEARCH_STEPS_DIAG); i++) {
+ e.rg = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ SMAA_FLATTEN if (dot(e, float2(1.0, 1.0)) < 1.9) break;
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ }
+ return i + float(e.g > 0.9) * c;
+}
+
+float SMAASearchDiag2(SMAATexture2D edgesTex, float2 texcoord, float2 dir, float c) {
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ float2 e = float2(0.0, 0.0);
+ float i;
+ for (i = 0.0; i < float(SMAA_MAX_SEARCH_STEPS_DIAG); i++) {
+ e.g = SMAASampleLevelZero(edgesTex, texcoord).g;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r;
+ SMAA_FLATTEN if (dot(e, float2(1.0, 1.0)) < 1.9) break;
+ texcoord += dir * SMAA_PIXEL_SIZE;
+ }
+ return i + float(e.g > 0.9) * c;
+}
+
+/**
+ * Similar to SMAAArea, this calculates the area corresponding to a certain
+ * diagonal distance and crossing edges 'e'.
+ */
+float2 SMAAAreaDiag(SMAATexture2D areaTex, float2 dist, float2 e, float offset) {
+ float2 texcoord = float(SMAA_AREATEX_MAX_DISTANCE_DIAG) * e + dist;
+
+ // We do a scale and bias for mapping to texel space:
+ texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + (0.5 * SMAA_AREATEX_PIXEL_SIZE);
+
+ // Diagonal areas are on the second half of the texture:
+ texcoord.x += 0.5;
+
+ // Move to proper place, according to the subpixel offset:
+ texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
+
+ // Do it!
+ return SMAASampleLevelZero(areaTex, texcoord).ra;
+}
+
+/**
+ * This searches for diagonal patterns and returns the corresponding weights.
+ */
+float2 SMAACalculateDiagWeights(SMAATexture2D edgesTex, SMAATexture2D areaTex, float2 texcoord, float2 e, int4 subsampleIndices) {
+ float2 weights = float2(0.0, 0.0);
+
+ float2 d;
+ d.x = e.r > 0.0? SMAASearchDiag1(edgesTex, texcoord, float2(-1.0, 1.0), 1.0) : 0.0;
+ d.y = SMAASearchDiag1(edgesTex, texcoord, float2(1.0, -1.0), 0.0);
+
+ SMAA_BRANCH
+ if (d.r + d.g > 2.0) { // d.r + d.g + 1 > 3
+ float4 coords = SMAAMad(float4(-d.r, d.r, d.g, -d.g), SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+
+ float4 c;
+ c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g;
+ c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0)).r;
+ c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).g;
+ c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1)).r;
+ float2 e = 2.0 * c.xz + c.yw;
+ float t = float(SMAA_MAX_SEARCH_STEPS_DIAG) - 1.0;
+ e *= step(d.rg, float2(t, t));
+
+ weights += SMAAAreaDiag(areaTex, d, e, float(subsampleIndices.z));
+ }
+
+ d.x = SMAASearchDiag2(edgesTex, texcoord, float2(-1.0, -1.0), 0.0);
+ float right = SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r;
+ d.y = right > 0.0? SMAASearchDiag2(edgesTex, texcoord, float2(1.0, 1.0), 1.0) : 0.0;
+
+ SMAA_BRANCH
+ if (d.r + d.g > 2.0) { // d.r + d.g + 1 > 3
+ float4 coords = SMAAMad(float4(-d.r, -d.r, d.g, d.g), SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+
+ float4 c;
+ c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g;
+ c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, -1)).r;
+ c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).gr;
+ float2 e = 2.0 * c.xz + c.yw;
+ float t = float(SMAA_MAX_SEARCH_STEPS_DIAG) - 1.0;
+ e *= step(d.rg, float2(t, t));
+
+ weights += SMAAAreaDiag(areaTex, d, e, float(subsampleIndices.w)).gr;
+ }
+
+ return weights;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Horizontal/Vertical Search Functions
+
+/**
+ * This allows to determine how much length should we add in the last step
+ * of the searches. It takes the bilinearly interpolated edge (see
+ * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and
+ * crossing edges are active.
+ */
+float SMAASearchLength(SMAATexture2D searchTex, float2 e, float bias, float scale) {
+ // Not required if searchTex accesses are set to point:
+ // float2 SEARCH_TEX_PIXEL_SIZE = 1.0 / float2(66.0, 33.0);
+ // e = float2(bias, 0.0) + 0.5 * SEARCH_TEX_PIXEL_SIZE +
+ // e * float2(scale, 1.0) * float2(64.0, 32.0) * SEARCH_TEX_PIXEL_SIZE;
+ e.r = bias + e.r * scale;
+ return 255.0 * SMAASampleLevelZeroPoint(searchTex, e).r;
+}
+
+/**
+ * Horizontal/vertical search functions for the 2nd pass.
+ */
+float SMAASearchXLeft(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ /**
+ * @PSEUDO_GATHER4
+ * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to
+ * sample between edge, thus fetching four edges in a row.
+ * Sampling with different offsets in each direction allows to disambiguate
+ * which edges are active from the four fetched ones.
+ */
+ float2 e = float2(0.0, 1.0);
+ while (texcoord.x > end &&
+ e.g > 0.8281 && // Is there some edge not activated?
+ e.r == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord -= float2(2.0, 0.0) * SMAA_PIXEL_SIZE;
+ }
+
+ // We correct the previous (-0.25, -0.125) offset we applied:
+ texcoord.x += 0.25 * SMAA_PIXEL_SIZE.x;
+
+ // The searches are bias by 1, so adjust the coords accordingly:
+ texcoord.x += SMAA_PIXEL_SIZE.x;
+
+ // Disambiguate the length added by the last step:
+ texcoord.x += 2.0 * SMAA_PIXEL_SIZE.x; // Undo last step
+ texcoord.x -= SMAA_PIXEL_SIZE.x * SMAASearchLength(searchTex, e, 0.0, 0.5);
+
+ return texcoord.x;
+}
+
+float SMAASearchXRight(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(0.0, 1.0);
+ while (texcoord.x < end &&
+ e.g > 0.8281 && // Is there some edge not activated?
+ e.r == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord += float2(2.0, 0.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.x -= 0.25 * SMAA_PIXEL_SIZE.x;
+ texcoord.x -= SMAA_PIXEL_SIZE.x;
+ texcoord.x -= 2.0 * SMAA_PIXEL_SIZE.x;
+ texcoord.x += SMAA_PIXEL_SIZE.x * SMAASearchLength(searchTex, e, 0.5, 0.5);
+ return texcoord.x;
+}
+
+float SMAASearchYUp(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(1.0, 0.0);
+ while (texcoord.y > end &&
+ e.r > 0.8281 && // Is there some edge not activated?
+ e.g == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord -= float2(0.0, 2.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.y += 0.25 * SMAA_PIXEL_SIZE.y;
+ texcoord.y += SMAA_PIXEL_SIZE.y;
+ texcoord.y += 2.0 * SMAA_PIXEL_SIZE.y;
+ texcoord.y -= SMAA_PIXEL_SIZE.y * SMAASearchLength(searchTex, e.gr, 0.0, 0.5);
+ return texcoord.y;
+}
+
+float SMAASearchYDown(SMAATexture2D edgesTex, SMAATexture2D searchTex, float2 texcoord, float end) {
+ float2 e = float2(1.0, 0.0);
+ while (texcoord.y < end &&
+ e.r > 0.8281 && // Is there some edge not activated?
+ e.g == 0.0) { // Or is there a crossing edge that breaks the line?
+ e = SMAASampleLevelZero(edgesTex, texcoord).rg;
+ texcoord += float2(0.0, 2.0) * SMAA_PIXEL_SIZE;
+ }
+
+ texcoord.y -= 0.25 * SMAA_PIXEL_SIZE.y;
+ texcoord.y -= SMAA_PIXEL_SIZE.y;
+ texcoord.y -= 2.0 * SMAA_PIXEL_SIZE.y;
+ texcoord.y += SMAA_PIXEL_SIZE.y * SMAASearchLength(searchTex, e.gr, 0.5, 0.5);
+ return texcoord.y;
+}
+
+/**
+ * Ok, we have the distance and both crossing edges. So, what are the areas
+ * at each side of current edge?
+ */
+float2 SMAAArea(SMAATexture2D areaTex, float2 dist, float e1, float e2, float offset) {
+ // Rounding prevents precision errors of bilinear filtering:
+ float2 texcoord = float(SMAA_AREATEX_MAX_DISTANCE) * round(4.0 * float2(e1, e2)) + dist;
+
+ // We do a scale and bias for mapping to texel space:
+ texcoord = SMAA_AREATEX_PIXEL_SIZE * texcoord + (0.5 * SMAA_AREATEX_PIXEL_SIZE);
+
+ // Move to proper place, according to the subpixel offset:
+ texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset;
+
+ // Do it!
+ return SMAASampleLevelZero(areaTex, texcoord).ra;
+}
+
+//-----------------------------------------------------------------------------
+// Corner Detection Functions
+
+void SMAADetectHorizontalCornerPattern(SMAATexture2D edgesTex, inout float2 weights, float2 texcoord, float2 d) {
+ #if SMAA_CORNER_ROUNDING < 100 || SMAA_FORCE_CORNER_DETECTION == 1
+ float4 coords = SMAAMad(float4(d.x, 0.0, d.y, 0.0),
+ SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+ float2 e;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(0.0, 1.0)).r;
+ bool left = abs(d.x) < abs(d.y);
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(0.0, -2.0)).r;
+ if (left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(1.0, 1.0)).r;
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(1.0, -2.0)).r;
+ if (!left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+ #endif
+}
+
+void SMAADetectVerticalCornerPattern(SMAATexture2D edgesTex, inout float2 weights, float2 texcoord, float2 d) {
+ #if SMAA_CORNER_ROUNDING < 100 || SMAA_FORCE_CORNER_DETECTION == 1
+ float4 coords = SMAAMad(float4(0.0, d.x, 0.0, d.y),
+ SMAA_PIXEL_SIZE.xyxy, texcoord.xyxy);
+ float2 e;
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 1.0, 0.0)).g;
+ bool left = abs(d.x) < abs(d.y);
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-2.0, 0.0)).g;
+ if (left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+
+ e.r = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1.0, 1.0)).g;
+ e.g = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2(-2.0, 1.0)).g;
+ if (!left) weights *= SMAASaturate(float(SMAA_CORNER_ROUNDING) / 100.0 + 1.0 - e);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// Blending Weight Calculation Pixel Shader (Second Pass)
+
+float4 SMAABlendingWeightCalculationPS(float2 texcoord,
+ float2 pixcoord,
+ float4 offset[3],
+ SMAATexture2D edgesTex,
+ SMAATexture2D areaTex,
+ SMAATexture2D searchTex,
+ int4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES.
+ float4 weights = float4(0.0, 0.0, 0.0, 0.0);
+
+ float2 e = SMAASample(edgesTex, texcoord).rg;
+
+ SMAA_BRANCH
+ if (e.g > 0.0) { // Edge at north
+ #if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+ // Diagonals have both north and west edges, so searching for them in
+ // one of the boundaries is enough.
+ weights.rg = SMAACalculateDiagWeights(edgesTex, areaTex, texcoord, e, subsampleIndices);
+
+ // We give priority to diagonals, so if we find a diagonal we skip
+ // horizontal/vertical processing.
+ SMAA_BRANCH
+ if (dot(weights.rg, float2(1.0, 1.0)) == 0.0) {
+ #endif
+
+ float2 d;
+
+ // Find the distance to the left:
+ float2 coords;
+ coords.x = SMAASearchXLeft(edgesTex, searchTex, offset[0].xy, offset[2].x);
+ coords.y = offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_PIXEL_SIZE.y (@CROSSING_OFFSET)
+ d.x = coords.x;
+
+ // Now fetch the left crossing edges, two at a time using bilinear
+ // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to
+ // discern what value each edge has:
+ float e1 = SMAASampleLevelZero(edgesTex, coords).r;
+
+ // Find the distance to the right:
+ coords.x = SMAASearchXRight(edgesTex, searchTex, offset[0].zw, offset[2].y);
+ d.y = coords.x;
+
+ // We want the distances to be in pixel units (doing this here allow to
+ // better interleave arithmetic and memory accesses):
+ d = d / SMAA_PIXEL_SIZE.x - pixcoord.x;
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically:
+ float2 sqrt_d = sqrt(abs(d));
+
+ // Fetch the right crossing edges:
+ float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, int2(1, 0)).r;
+
+ // Ok, we know how this pattern looks like, now it is time for getting
+ // the actual area:
+ weights.rg = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.y));
+
+ // Fix corners:
+ SMAADetectHorizontalCornerPattern(edgesTex, weights.rg, texcoord, d);
+
+ #if SMAA_MAX_SEARCH_STEPS_DIAG > 0 || SMAA_FORCE_DIAGONAL_DETECTION == 1
+ } else
+ e.r = 0.0; // Skip vertical processing.
+ #endif
+ }
+
+ SMAA_BRANCH
+ if (e.r > 0.0) { // Edge at west
+ float2 d;
+
+ // Find the distance to the top:
+ float2 coords;
+ coords.y = SMAASearchYUp(edgesTex, searchTex, offset[1].xy, offset[2].z);
+ coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_PIXEL_SIZE.x;
+ d.x = coords.y;
+
+ // Fetch the top crossing edges:
+ float e1 = SMAASampleLevelZero(edgesTex, coords).g;
+
+ // Find the distance to the bottom:
+ coords.y = SMAASearchYDown(edgesTex, searchTex, offset[1].zw, offset[2].w);
+ d.y = coords.y;
+
+ // We want the distances to be in pixel units:
+ d = d / SMAA_PIXEL_SIZE.y - pixcoord.y;
+
+ // SMAAArea below needs a sqrt, as the areas texture is compressed
+ // quadratically:
+ float2 sqrt_d = sqrt(abs(d));
+
+ // Fetch the bottom crossing edges:
+ float e2 = SMAASampleLevelZeroOffset(edgesTex, coords, int2(0, 1)).g;
+
+ // Get the area for this direction:
+ weights.ba = SMAAArea(areaTex, sqrt_d, e1, e2, float(subsampleIndices.x));
+
+ // Fix corners:
+ SMAADetectVerticalCornerPattern(edgesTex, weights.ba, texcoord, d);
+ }
+
+ return weights;
+}
+
+//-----------------------------------------------------------------------------
+// Neighborhood Blending Pixel Shader (Third Pass)
+
+float4 SMAANeighborhoodBlendingPS(float2 texcoord,
+ float4 offset[2],
+ SMAATexture2D colorTex,
+ SMAATexture2D blendTex) {
+ // Fetch the blending weights for current pixel:
+ float4 a;
+ a.xz = SMAASample(blendTex, texcoord).xz;
+ a.y = SMAASample(blendTex, offset[1].zw).g;
+ a.w = SMAASample(blendTex, offset[1].xy).a;
+
+ // Is there any blending weight with a value greater than 0.0?
+ SMAA_BRANCH
+ if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
+ return SMAASampleLevelZero(colorTex, texcoord);
+ else {
+ float4 color = float4(0.0, 0.0, 0.0, 0.0);
+
+ // Up to 4 lines can be crossing a pixel (one through each edge). We
+ // favor blending by choosing the line with the maximum weight for each
+ // direction:
+ float2 offset;
+ offset.x = a.a > a.b? a.a : -a.b; // left vs. right
+ offset.y = a.g > a.r? a.g : -a.r; // top vs. bottom
+
+ // Then we go in the direction that has the maximum weight:
+ if (abs(offset.x) > abs(offset.y)) // horizontal vs. vertical
+ offset.y = 0.0;
+ else
+ offset.x = 0.0;
+
+ #if SMAA_REPROJECTION == 1
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZero(colorTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZero(colorTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+
+ // Unpack the velocity values:
+ C.a *= C.a;
+ Cop.a *= Cop.a;
+
+ // Lerp the colors:
+ float4 Caa = SMAALerp(C, Cop, s);
+
+ // Unpack velocity and return the resulting value:
+ Caa.a = sqrt(Caa.a);
+ return Caa;
+ #elif SMAA_HLSL_4 == 1 || SMAA_DIRECTX9_LINEAR_BLEND == 0
+ // We exploit bilinear filtering to mix current pixel with the chosen
+ // neighbor:
+ texcoord += offset * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZero(colorTex, texcoord);
+ #else
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZero(colorTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZero(colorTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+ return SMAALerp(C, Cop, s);
+ #endif
+ }
+}
+
+float4 SMAASampleLevelZeroResolve( SMAATexture2D currentTex,
+ SMAATexture2D previousTex,
+ float2 texcoord )
+{
+ return SMAALerp( SMAASampleLevelZero( currentTex, texcoord ), SMAASampleLevelZero( previousTex, texcoord ), .5 );
+}
+
+float4 SMAANeighborhoodBlendingTemporalPS(float2 texcoord,
+ float4 offset[2],
+ SMAATexture2D colorTex,
+ SMAATexture2D previousTex,
+ SMAATexture2D blendTex) {
+ // Fetch the blending weights for current pixel:
+ float4 a;
+ a.xz = SMAASample(blendTex, texcoord).xz;
+ a.y = SMAASample(blendTex, offset[1].zw).g;
+ a.w = SMAASample(blendTex, offset[1].xy).a;
+
+ // Is there any blending weight with a value greater than 0.0?
+ SMAA_BRANCH
+ if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5)
+ return SMAASampleLevelZero(colorTex, texcoord);
+ else {
+ float4 color = float4(0.0, 0.0, 0.0, 0.0);
+
+ // Up to 4 lines can be crossing a pixel (one through each edge). We
+ // favor blending by choosing the line with the maximum weight for each
+ // direction:
+ float2 offset;
+ offset.x = a.a > a.b? a.a : -a.b; // left vs. right
+ offset.y = a.g > a.r? a.g : -a.r; // top vs. bottom
+
+ // Then we go in the direction that has the maximum weight:
+ if (abs(offset.x) > abs(offset.y)) // horizontal vs. vertical
+ offset.y = 0.0;
+ else
+ offset.x = 0.0;
+
+ #if SMAA_REPROJECTION == 1
+ // Fetch the opposite color and lerp by hand:
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+
+ // Unpack the velocity values:
+ C.a *= C.a;
+ Cop.a *= Cop.a;
+
+ // Lerp the colors:
+ float4 Caa = SMAALerp(C, Cop, s);
+
+ // Unpack velocity and return the resulting value:
+ Caa.a = sqrt(Caa.a);
+ return Caa;
+ #elif SMAA_HLSL_4 == 1 || SMAA_DIRECTX9_LINEAR_BLEND == 0
+ // We exploit bilinear filtering to mix current pixel with the chosen
+ // neighbor:
+ texcoord += offset * SMAA_PIXEL_SIZE;
+ return SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ #else
+ // Fetch the opposite color and lerp by hand:
+ float4 C = SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ texcoord += sign(offset) * SMAA_PIXEL_SIZE;
+ float4 Cop = SMAASampleLevelZeroResolve(colorTex, previousTex, texcoord);
+ float s = abs(offset.x) > abs(offset.y)? abs(offset.x) : abs(offset.y);
+ return SMAALerp(C, Cop, s);
+ #endif
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Temporal Resolve Pixel Shader (Optional Pass)
+
+float4 SMAAResolvePS(float2 texcoord,
+ SMAATexture2D colorTexCurr,
+ SMAATexture2D colorTexPrev
+ #if SMAA_REPROJECTION == 1
+ , SMAATexture2D velocityTex
+ #endif
+ ) {
+ #if SMAA_REPROJECTION == 1
+ // Velocity is calculated from previous to current position, so we need to
+ // inverse it:
+ float2 velocity = -SMAASample(velocityTex, texcoord).rg;
+
+ // Fetch current pixel:
+ float4 current = SMAASample(colorTexCurr, texcoord);
+
+ // Reproject current coordinates and fetch previous pixel:
+ float4 previous = SMAASample(colorTexPrev, texcoord + velocity);
+
+ // Attenuate the previous pixel if the velocity is different:
+ float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0;
+ float weight = 0.5 * SMAASaturate(1.0 - (sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE));
+
+ // Blend the pixels according to the calculated weight:
+ return SMAALerp(current, previous, weight);
+ #else
+ // Just blend the pixels:
+ float4 current = SMAASample(colorTexCurr, texcoord);
+ float4 previous = SMAASample(colorTexPrev, texcoord);
+ return SMAALerp(current, previous, 0.5);
+ #endif
+}
+
+//-----------------------------------------------------------------------------
+// Separate Multisamples Pixel Shader (Optional Pass)
+
+#if SMAA_HLSL_4 == 1 || SMAA_HLSL_4_1 == 1
+void SMAASeparatePS(float4 position : SV_POSITION,
+ float2 texcoord : TEXCOORD0,
+ out float4 target0,
+ out float4 target1,
+ uniform SMAATexture2DMS2 colorTexMS) {
+ int2 pos = int2(position.xy);
+ target0 = SMAALoad(colorTexMS, pos, 0);
+ target1 = SMAALoad(colorTexMS, pos, 1);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+#endif // SMAA_ONLY_COMPILE_VS == 0
diff --git a/res/effectlib/SSAOCustomMaterial.glsllib b/res/effectlib/SSAOCustomMaterial.glsllib
new file mode 100644
index 0000000..1d8a1c3
--- /dev/null
+++ b/res/effectlib/SSAOCustomMaterial.glsllib
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 SSAO_CUSTOM_MATERIAL_GLSLLIB
+#define SSAO_CUSTOM_MATERIAL_GLSLLIB
+#if QT3DS_ENABLE_SSAO || QT3DS_ENABLE_SSDO
+
+#include "viewProperties.glsllib"
+#if QT3DS_ENABLE_SSDO
+#include "screenSpaceDO.glsllib"
+
+layout (std140) uniform cbAoShadow {
+ vec4 ao_properties;
+ vec4 ao_properties2;
+ vec4 shadow_properties;
+ vec4 aoScreenConst;
+ vec4 UvToEyeConst;
+ };
+
+uniform sampler2D depth_sampler;
+#endif
+uniform sampler2D ao_sampler;
+
+#endif // QT3DS_ENABLE_SSAO || QT3DS_ENABLE_SSDO
+
+#if QT3DS_ENABLE_SSAO
+
+float customMaterialAO()
+{
+#if QT3DS_ENABLE_SSDO
+ vec2 smpUV = (gl_FragCoord.xy) * aoScreenConst.zw;
+#else
+ ivec2 iSize = textureSize(ao_sampler, 0);
+ vec2 smpUV = (gl_FragCoord.xy) / vec2(iSize);
+#endif
+ return texture(ao_sampler, smpUV).x;
+}
+
+#else
+
+float customMaterialAO()
+{
+ return 1.0;
+}
+
+#endif
+
+#if QT3DS_ENABLE_SSDO
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return shadowOcclusion( depth_sampler, lightDir, varWorldPos, view_matrix, view_projection_matrix, shadow_properties, camera_properties, aoScreenConst, UvToEyeConst );
+}
+
+#else
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return 1.0;
+}
+
+#endif
+
+#endif // #ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
diff --git a/res/effectlib/abbeNumberIOR.glsllib b/res/effectlib/abbeNumberIOR.glsllib
new file mode 100644
index 0000000..43ed79d
--- /dev/null
+++ b/res/effectlib/abbeNumberIOR.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// TODO: compute spectral ior based on float ior and abbe number
+vec3 abbeNumberIOR( in float ior, in float abbeNumber )
+{
+ return( vec3( ior, ior, ior ) );
+}
+
diff --git a/res/effectlib/anisotropyConversion.glsllib b/res/effectlib/anisotropyConversion.glsllib
new file mode 100644
index 0000000..b8aae1e
--- /dev/null
+++ b/res/effectlib/anisotropyConversion.glsllib
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2014-2015 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$
+**
+****************************************************************************/
+
+
+// TODO: real implementation
+anisotropy_return anisotropyConversion( in float roughness, in float anisotropy, in float anisotropyRotation, in vec3 tangentU, bool miaAnisotropySemantic )
+{
+ anisotropy_return aniso;
+ float angle = 2.0 * PI * anisotropyRotation;
+ float cos_angle = cos(angle);
+ float sin_angle = sin(angle);
+ aniso.tangent_u = normalize( cos_angle * tangentU + sin_angle * binormal );
+ // roughness
+ float anisoFac = 1.0 - clamp(anisotropy, 0.0, 0.999);
+ aniso.roughness_v = clamp( roughness / anisoFac, 0.0001, 1.0);
+ aniso.roughness_u = clamp( aniso.roughness_v * anisoFac, 0.0001, 1.0);
+ return( aniso );
+}
+
diff --git a/res/effectlib/average.glsllib b/res/effectlib/average.glsllib
new file mode 100644
index 0000000..082eec0
--- /dev/null
+++ b/res/effectlib/average.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float average( in vec3 v )
+{
+ return( ( v.x + v.y + v.z ) / 3.0 );
+}
+
diff --git a/res/effectlib/blendColorLayers.glsllib b/res/effectlib/blendColorLayers.glsllib
new file mode 100644
index 0000000..e07fe61
--- /dev/null
+++ b/res/effectlib/blendColorLayers.glsllib
@@ -0,0 +1,45 @@
+#ifndef BLEND_COLOR_LAYERS_GLSLLIB
+#define BLEND_COLOR_LAYERS_GLSLLIB
+
+float maxValue( in vec3 t )
+{
+ return max( max( t.x, t.y ), t.z );
+}
+
+vec3 blendColor( in vec3 t, in vec3 b, in float weight, in int blendMode)
+{
+ vec3 blendResult = t;
+ switch( blendMode )
+ {
+ case color_layer_add :
+ blendResult += b;
+ break;
+ case color_layer_multiply :
+ blendResult *= b;
+ break;
+ case color_layer_screen :
+ blendResult += t - t * b;
+ break;
+ case color_layer_overlay:
+ blendResult = (maxValue(t) >= 0.5) ? 2.0 * (t+b - t*b - 0.5) : 2.0 * t*b;
+ break;
+ case color_layer_blend:
+ default:
+ // nothing to be done
+ break;
+ }
+
+ return mix( b, blendResult, weight );
+}
+
+texture_return blendColorLayers( in color_layer colorLayer[1], in vec3 base, in int monoSource )
+{
+ vec3 result = blendColor( colorLayer[0].layer_color, base, colorLayer[0].weight, colorLayer[0].mode );
+
+ texture_return tr;
+ tr.tint = result;
+ tr.mono = monoChannel( vec4( result, 1.0 ), monoSource );
+ return( tr );
+}
+
+#endif
diff --git a/res/effectlib/blur.glsllib b/res/effectlib/blur.glsllib
new file mode 100644
index 0000000..1f3abc8
--- /dev/null
+++ b/res/effectlib/blur.glsllib
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** 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 BLUR_GLSLLIB
+#define BLUR_GLSLLIB 1
+#include "depthpass.glsllib"
+varying float xIncrement;
+varying float yIncrement;
+varying vec2 TexCoord0;
+varying vec2 TexCoord1;
+varying vec2 TexCoord2;
+varying vec2 TexCoord3;
+varying vec2 TexCoord4;
+varying vec2 TexCoord5;
+varying vec2 TexCoord6;
+varying vec2 TexCoord7;
+
+
+const vec3 poisson0 = vec3( 0.000000, 0.000000, 0.000000 );
+const vec3 poisson1 = vec3( 0.527837, -0.085868, 0.534776 );
+const vec3 poisson2 = vec3( -0.040088, 0.537087, 0.538581 );
+const vec3 poisson3 = vec3( -0.670445, -0.017995, 0.670686 );
+const vec3 poisson4 = vec3( -0.419418, -0.616039, 0.745262 );
+const vec3 poisson5 = vec3( 0.440453, -0.639399, 0.776421 );
+const vec3 poisson6 = vec3( -0.757088, 0.349334, 0.833796 );
+const vec3 poisson7 = vec3( 0.574619, 0.685879, 0.894772 );
+
+//7 textel gaussian
+#define WT7_0 20.0
+#define WT7_1 15.0
+#define WT7_2 6.0
+#define WT7_3 1.0
+#define WT7_NORMALIZE (WT7_0+2.0*(WT7_1+WT7_2+WT7_3))
+
+//3 textel gaussian
+#define WT3_0 1.0
+#define WT3_1 0.6
+#define WT3_NORMALIZE (WT3_0+2.0*(WT3_1))
+
+uniform vec2 CameraClipRange;
+
+float GetDepthMultiplier(vec2 inTexCoord, sampler2D inDepthSampler, float inFocusDistance, float inFocusWidth, float inFocusPenumbra)
+{
+ float depthTap = getDepthValue( texture2D(inDepthSampler, inTexCoord), CameraClipRange );
+ float linearDepth = depthValueToLinearDistance( depthTap, CameraClipRange );
+ float depthDiff = max( 0.0, abs( linearDepth - inFocusDistance ) - (inFocusWidth/2.0) ) / inFocusPenumbra;
+ return clamp( depthDiff, 0.0, 1.0 );
+}
+
+float GetTiltShiftMultiplier(vec2 inTexCoord, float inFocusBarHeight, float inFocusWidth )
+{
+ //For now, you can't rotate the focus blur but in time you will be able to.
+ float texPos = inTexCoord.y;
+ float focusDiff = max( 0.0, abs( texPos - inFocusBarHeight ) - (inFocusWidth/2.0) ) / inFocusWidth;
+ return clamp( focusDiff, 0.0, 1.0 );
+}
+
+#ifdef VERTEX_SHADER
+
+void SetupBoxBlurCoords(vec2 inTexInfo)
+{
+ xIncrement = .5 / inTexInfo.x;
+ yIncrement = .5 / inTexInfo.y;
+ TexCoord0 = vec2( TexCoord.x + xIncrement, TexCoord.y + yIncrement );
+ TexCoord1 = vec2( TexCoord.x - xIncrement, TexCoord.y - yIncrement );
+ TexCoord2 = vec2( TexCoord.x - xIncrement, TexCoord.y + yIncrement );
+ TexCoord3 = vec2( TexCoord.x + xIncrement, TexCoord.y - yIncrement );
+}
+
+void SetupPoissonBlurCoords(float inBlurAmount, vec2 inTexInfo )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ TexCoord0 = vec2( TexCoord.x + poisson0.x * incX, TexCoord.y + poisson0.y * incY );
+ TexCoord1 = vec2( TexCoord.x + poisson1.x * incX, TexCoord.y + poisson1.y * incY );
+ TexCoord2 = vec2( TexCoord.x + poisson2.x * incX, TexCoord.y + poisson2.y * incY );
+ TexCoord3 = vec2( TexCoord.x + poisson3.x * incX, TexCoord.y + poisson3.y * incY );
+ TexCoord4 = vec2( TexCoord.x + poisson4.x * incX, TexCoord.y + poisson4.y * incY );
+ TexCoord5 = vec2( TexCoord.x + poisson5.x * incX, TexCoord.y + poisson5.y * incY );
+ TexCoord6 = vec2( TexCoord.x + poisson6.x * incX, TexCoord.y + poisson6.y * incY );
+ TexCoord7 = vec2( TexCoord.x + poisson7.x * incX, TexCoord.y + poisson7.y * incY );
+}
+
+void SetupHorizontalGaussianBlur( float inDestWidth, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestWidth;
+ TexCoord0 = vec2(inTexCoord.x + increment , inTexCoord.y );
+ TexCoord1 = vec2(inTexCoord.x + increment * 2.0 , inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x + increment * 3.0 , inTexCoord.y);
+ TexCoord3 = vec2(inTexCoord.x , inTexCoord.y);
+ TexCoord4 = vec2(inTexCoord.x - increment , inTexCoord.y);
+ TexCoord5 = vec2(inTexCoord.x - increment * 2.0 , inTexCoord.y);
+ TexCoord6 = vec2(inTexCoord.x - increment * 3.0 , inTexCoord.y);
+}
+
+void SetupVerticalGaussianBlur( float inDestHeight, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestHeight;
+ TexCoord0 = vec2(inTexCoord.x, inTexCoord.y + increment );
+ TexCoord1 = vec2(inTexCoord.x, inTexCoord.y + increment * 2.0 );
+ TexCoord2 = vec2(inTexCoord.x, inTexCoord.y + increment * 3.0);
+ TexCoord3 = vec2(inTexCoord.x, inTexCoord.y);
+ TexCoord4 = vec2(inTexCoord.x, inTexCoord.y - increment);
+ TexCoord5 = vec2(inTexCoord.x, inTexCoord.y - increment * 2.0);
+ TexCoord6 = vec2(inTexCoord.x, inTexCoord.y - increment * 3.0);
+}
+
+void SetupHorizontalGaussianBlur3Tap( float inDestWidth, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestWidth;
+ TexCoord0 = vec2(inTexCoord.x + increment , inTexCoord.y );
+ TexCoord1 = vec2(inTexCoord.x , inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x - increment , inTexCoord.y);
+}
+
+void SetupVerticalGaussianBlur3Tap( float inDestHeight, float inBlurAmount, vec2 inTexCoord )
+{
+ float increment = inBlurAmount/inDestHeight;
+ TexCoord0 = vec2(inTexCoord.x, inTexCoord.y + increment );
+ TexCoord1 = vec2(inTexCoord.x, inTexCoord.y);
+ TexCoord2 = vec2(inTexCoord.x, inTexCoord.y - increment);
+}
+
+#endif
+
+#ifdef FRAGMENT_SHADER
+
+vec4 BoxDepthBlur(sampler2D inDepthSampler, sampler2D inBlurSampler, float inBlurSamplerAlphaFlag
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ float mult0 = .25 * GetDepthMultiplier( TexCoord0, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult1 = .25 * GetDepthMultiplier( TexCoord1, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult2 = .25 * GetDepthMultiplier( TexCoord2, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float mult3 = .25 * GetDepthMultiplier( TexCoord3, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra );
+ float multTotal = mult0 + mult1 + mult2 + mult3;
+ float totalDivisor = multTotal != 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = GetTextureValue(inBlurSampler, TexCoord0, inBlurSamplerAlphaFlag) * mult0;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord1, inBlurSamplerAlphaFlag) * mult1;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord2, inBlurSamplerAlphaFlag) * mult2;
+ OutCol += GetTextureValue(inBlurSampler, TexCoord3, inBlurSamplerAlphaFlag) * mult3;
+ return OutCol * totalDivisor;
+}
+
+vec4 BoxTiltShiftBlur( sampler2D inBlurSampler, float inBlurSamplerAlphaFlag
+ , float inFocusBarHeight, float inFocusWidth )
+{
+ float mult0 = .25 * GetTiltShiftMultiplier( TexCoord0, inFocusBarHeight, inFocusWidth );
+ float mult1 = .25 * GetTiltShiftMultiplier( TexCoord1, inFocusBarHeight, inFocusWidth );
+ float mult2 = .25 * GetTiltShiftMultiplier( TexCoord2, inFocusBarHeight, inFocusWidth );
+ float mult3 = .25 * GetTiltShiftMultiplier( TexCoord3, inFocusBarHeight, inFocusWidth );
+ float multTotal = mult0 + mult1 + mult2 + mult3;
+ float totalDivisor = multTotal != 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = GetTextureValuePreMult(inBlurSampler, TexCoord0) * mult0;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord1) * mult1;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord2) * mult2;
+ OutCol += GetTextureValuePreMult(inBlurSampler, TexCoord3) * mult3;
+ return OutCol * totalDivisor;
+}
+
+vec4 PoissonDepthBlur(sampler2D inSampler, float inAlphaFlag, sampler2D inDepthSampler
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ float mult0 = (1.0 - poisson0.z) * GetDepthMultiplier(TexCoord0,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+ float mult1 = (1.0 - poisson1.z) * GetDepthMultiplier(TexCoord1,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+ float mult2 = (1.0 - poisson2.z) * GetDepthMultiplier(TexCoord2,inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra);
+
+ float multTotal = mult0 + mult1 + mult2;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+
+ vec4 outColor = GetTextureValue( inSampler, TexCoord0, inAlphaFlag ) * (mult0 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord1, inAlphaFlag ) * (mult1 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord2, inAlphaFlag ) * (mult2 * multMultiplier);
+ return outColor;
+}
+
+vec4 PoissonTiltShiftBlur(sampler2D inSampler, float inAlphaFlag, float inBarHeight, float inFocusWidth )
+{
+ float mult0 = (1.0 - poisson0.z) * GetTiltShiftMultiplier(TexCoord0, inBarHeight, inFocusWidth );
+ float mult1 = (1.0 - poisson1.z) * GetTiltShiftMultiplier(TexCoord1, inBarHeight, inFocusWidth );
+ float mult2 = (1.0 - poisson2.z) * GetTiltShiftMultiplier(TexCoord2, inBarHeight, inFocusWidth );
+ float mult3 = (1.0 - poisson3.z) * GetTiltShiftMultiplier(TexCoord3, inBarHeight, inFocusWidth );
+ float mult4 = (1.0 - poisson4.z) * GetTiltShiftMultiplier(TexCoord4, inBarHeight, inFocusWidth );
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+
+ vec4 outColor = GetTextureValuePreMult( inSampler, TexCoord0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord1 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord2 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord3 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValuePreMult( inSampler, TexCoord4 ) * (mult4 * multMultiplier);
+ return outColor;
+}
+
+float GaussianAlphaBlur( sampler2D inSampler, float inAlphaFlag )
+{
+ float OutCol = 0.0;
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag).a * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag).a * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag).a * ( WT7_3/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord3, inAlphaFlag).a * ( WT7_0/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord4, inAlphaFlag).a * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord5, inAlphaFlag).a * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord6, inAlphaFlag).a * ( WT7_3/WT7_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianBlur( sampler2D inSampler, float inAlphaFlag )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag) * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag) * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag) * ( WT7_3/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord3, inAlphaFlag) * ( WT7_0/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord4, inAlphaFlag) * ( WT7_1/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord5, inAlphaFlag) * ( WT7_2/WT7_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord6, inAlphaFlag) * ( WT7_3/WT7_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianBlur3Tap( sampler2D inSampler, float inAlphaFlag )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inAlphaFlag) * ( WT3_1/WT3_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord1, inAlphaFlag) * ( WT3_0/WT3_NORMALIZE );
+ OutCol += GetTextureValue(inSampler, TexCoord2, inAlphaFlag) * ( WT3_1/WT3_NORMALIZE );
+ return OutCol;
+}
+
+//Get texture data for a texture we know is premultiplied.
+vec4 GaussianBlur3TapPremultiplied( sampler2D inSampler )
+{
+ vec4 OutCol = vec4(0.0);
+ OutCol += texture2D(inSampler, TexCoord0) * ( WT3_1/WT3_NORMALIZE );
+ OutCol += texture2D(inSampler, TexCoord1) * ( WT3_0/WT3_NORMALIZE );
+ OutCol += texture2D(inSampler, TexCoord2) * ( WT3_1/WT3_NORMALIZE );
+ return OutCol;
+}
+
+vec4 GaussianDepthBlur( sampler2D inSampler, float inTextureAlphaInfo, sampler2D inDepthSampler
+ , float inFocusDistance, float inFocusWidth, float inFocusPenumbra )
+{
+ //We modulate each sample weight by the depth value so that we minimize bleeding of the focused
+ //area into the non-focused area.
+ float mult0 = GetDepthMultiplier(TexCoord0, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_1;
+ float mult1 = GetDepthMultiplier(TexCoord1, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_2;
+ float mult2 = GetDepthMultiplier(TexCoord2, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_3;
+ float mult3 = GetDepthMultiplier(TexCoord3, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_0;
+ float mult4 = GetDepthMultiplier(TexCoord4, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_1;
+ float mult5 = GetDepthMultiplier(TexCoord5, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_2;
+ float mult6 = GetDepthMultiplier(TexCoord6, inDepthSampler, inFocusDistance, inFocusWidth, inFocusPenumbra) * WT7_3;
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6;
+ float multMultiplier = multTotal > 0.0 ? 1.0 / multTotal : 0.0;
+ vec4 OutCol = vec4(0.0);
+ OutCol += GetTextureValue(inSampler, TexCoord0, inTextureAlphaInfo) * (mult0 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord1, inTextureAlphaInfo) * (mult1 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord2, inTextureAlphaInfo) * (mult2 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord3, inTextureAlphaInfo) * (mult3 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord4, inTextureAlphaInfo) * (mult4 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord5, inTextureAlphaInfo) * (mult5 * multMultiplier);
+ OutCol += GetTextureValue(inSampler, TexCoord6, inTextureAlphaInfo) * (mult6 * multMultiplier);
+ return OutCol;
+}
+
+#endif
+
+
+#endif // BLUR_GLSLLIB
diff --git a/res/effectlib/calculateRoughness.glsllib b/res/effectlib/calculateRoughness.glsllib
new file mode 100644
index 0000000..a14083d
--- /dev/null
+++ b/res/effectlib/calculateRoughness.glsllib
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float calculateRoughness( in vec3 N, in float roughnessU, in float roughnessV, in vec3 tangentU )
+{
+ float roughness = roughnessU;
+ if ( abs(roughnessU - roughnessV) > 0.00001)
+ {
+ // determine major and minor radii a and b, and the vector along the major axis
+ float a = roughnessU;
+ float b = roughnessV;
+
+ // we need the angle between the major axis and the projection of viewDir on the tangential plane
+ // the major axis is the orthonormalization of tangentU with respect to N
+ // the projection of viewDir is the orthonormalization of viewDir with respect to N
+ // as both vectors would be calculated by orthonormalize, we can as well leave the second cross
+ // product in those calculations away, as they don't change the angular relation.
+ vec3 minorAxis = normalize( cross( tangentU, N ) ); // crossing this with N would give the major axis
+ // which is equivalent to orthonormalizing tangentU with respect to N
+ if ( roughnessU < roughnessV )
+ {
+ a = roughnessV;
+ b = roughnessU;
+ minorAxis = cross( N, minorAxis );
+ }
+
+ vec3 po = normalize( cross( viewDir, N ) );
+ float cosPhi = dot( po, minorAxis );
+
+ // determine the polar coordinate of viewDir, take that radius as the roughness
+ float excentricitySquare = 1.0 - square( b / a );
+ roughness = b / sqrt( 1.0 - excentricitySquare * square( cosPhi ) );
+ }
+ return( roughness );
+}
+
diff --git a/res/effectlib/coordinateSource.glsllib b/res/effectlib/coordinateSource.glsllib
new file mode 100644
index 0000000..bc435d5
--- /dev/null
+++ b/res/effectlib/coordinateSource.glsllib
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+texture_coordinate_info coordinateSource( in int coordinateSystem, in int textureSpace )
+{
+ texture_coordinate_info tci;
+ switch( coordinateSystem )
+ {
+ case texture_coordinate_object :
+ tci.position = varObjPos;
+ tci.tangent_u = normalize( varObjTangent );
+ tci.tangent_v = normalize( varObjBinormal );
+ break;
+ case texture_coordinate_world :
+ tci.position = varWorldPos;
+ tci.tangent_u = normalize( varTangent );
+ tci.tangent_v = normalize( varBinormal );
+ break;
+ case texture_coordinate_uvw :
+ default :
+ tci.position = varTexCoord0;
+ tci.tangent_u = normalize( varTangent );
+ tci.tangent_v = normalize( varBinormal );
+ break;
+ }
+ return( tci );
+}
+
diff --git a/res/effectlib/cube.glsllib b/res/effectlib/cube.glsllib
new file mode 100644
index 0000000..74da833
--- /dev/null
+++ b/res/effectlib/cube.glsllib
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float cube( in float x )
+{
+ return( x * x * x );
+}
+
+vec2 cube( in vec2 x )
+{
+ return( x * x * x );
+}
+
+vec3 cube( in vec3 x )
+{
+ return( x * x * x );
+}
+
+vec4 cube( in vec4 x )
+{
+ return( x * x * x );
+}
+
diff --git a/res/effectlib/customCurveLayer.glsllib b/res/effectlib/customCurveLayer.glsllib
new file mode 100644
index 0000000..2bc1780
--- /dev/null
+++ b/res/effectlib/customCurveLayer.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 customCurveLayer( in vec3 L, in float normal_reflectivity, in float grazing_reflectivity, in float exponent, float weight, in vec3 layercolor, vec4 layer, vec4 base, in float alpha )
+{
+ vec3 H = normalize( viewDir + L );
+ vec3 refl = reflect( -viewDir, H );
+ float reflWt = clamp( dot( surfNormal, refl ) + 1.0, 0.0, 1.0 );
+
+ float curveFactor = mix( normal_reflectivity, grazing_reflectivity, pow(1.0 - abs(dot( viewDir, H )), exponent) );
+ curveFactor *= weight * reflWt;
+
+ return( vec4( mix( base.rgb, layercolor * layer.rgb, curveFactor ), mix(alpha, 1.0, curveFactor) ) );
+}
+
diff --git a/res/effectlib/customMaterial.glsllib b/res/effectlib/customMaterial.glsllib
new file mode 100644
index 0000000..0a4d88b
--- /dev/null
+++ b/res/effectlib/customMaterial.glsllib
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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 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
+#define PI_HALF ( 0.5 * PI )
+#define PI_TWO ( 2.0 * PI )
+#define ONE_OVER_PI ( 1.0 / PI )
+#define TWO_OVER_PI ( 2.0 / PI )
+#define PI_SQUARE ( PI * PI )
+#endif
+
+#endif // CUSTOM_MATERIAL_GLSLLIB
diff --git a/res/effectlib/customMaterialFragBody.glsllib b/res/effectlib/customMaterialFragBody.glsllib
new file mode 100644
index 0000000..fccb8e0
--- /dev/null
+++ b/res/effectlib/customMaterialFragBody.glsllib
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB
+#define CUSTOM_MATERIAL_FRAG_BODY_GLSLLIB
+
+ bool twoSided = false;
+ vec3 materialEmissive = vec3( 0.0, 0.0, 0.0 );
+
+ float materialIOR = computeIOR();
+
+ if ( gl_FrontFacing )
+ {
+ materialEmissive = computeFrontMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ else
+ {
+ materialIOR = 1.0 / materialIOR;
+ twoSided = evalTwoSided();
+ if ( twoSided )
+ {
+ normal = -normal;
+ materialEmissive = computeBackMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ }
+
+ vec4 rgba = vec4( materialEmissive, 0.0 );
+
+ vec3 lightAmbient, lightDiffuse, lightSpecular, L;
+ for ( int i=0 ; i<uNumLights ; i++ )
+ {
+ sampleLight( lights[i], varWorldPos, L, lightAmbient, lightDiffuse, lightSpecular);
+ //evalTemporariesPerLightSource( normal, L, lightDiffuse, lightSpecular, materialIOR );
+ if (gl_FrontFacing)
+ computeFrontLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, 1.0 );
+ else
+ computeBackLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, 1.0 );
+ }
+ for ( int i=0 ; i < uNumAreaLights; ++i )
+ {
+ if (gl_FrontFacing)
+ computeFrontAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ else
+ computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ }
+
+ if ( 0.0 < alpha )
+ {
+ if (gl_FrontFacing)
+ computeFrontLayerEnvironment( normal, viewDir, 1.0 );
+ else
+ computeBackLayerEnvironment( normal, viewDir, 1.0 );
+ }
+
+ rgba += computeLayerWeights( alpha );
+
+#endif
diff --git a/res/effectlib/customMaterialFragBodyAO.glsllib b/res/effectlib/customMaterialFragBodyAO.glsllib
new file mode 100644
index 0000000..d194569
--- /dev/null
+++ b/res/effectlib/customMaterialFragBodyAO.glsllib
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** 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 CUSTOM_MATERIAL_FRAG_BODY_AO_GLSLLIB
+#define CUSTOM_MATERIAL_FRAG_BODY_AO_GLSLLIB
+
+ bool twoSided = false;
+ vec3 materialEmissive = vec3( 0.0, 0.0, 0.0 );
+
+ float materialIOR = computeIOR();
+
+ if ( gl_FrontFacing )
+ {
+ materialEmissive = computeFrontMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ else
+ {
+ materialIOR = 1.0 / materialIOR;
+ twoSided = evalTwoSided();
+ if ( twoSided )
+ {
+ normal = -normal;
+ materialEmissive = computeBackMaterialEmissive() * computeMaterialEmissiveMask();
+ }
+ }
+
+ vec4 rgba = vec4( materialEmissive, 0.0 );
+
+ // compute ambient occlusion
+ float aoFactor = customMaterialAO( );
+
+ vec3 lightAmbient, lightDiffuse, lightSpecular, L;
+ for ( int i=0 ; i<uNumLights ; i++ )
+ {
+ sampleLight( lights[i], varWorldPos, L, lightAmbient, lightDiffuse, lightSpecular);
+ lightAmbient *= aoFactor;
+ lightDiffuse *= aoFactor;
+
+ //evalTemporariesPerLightSource( normal, L, lightDiffuse, lightSpecular, materialIOR );
+ if (gl_FrontFacing)
+ computeFrontLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, aoFactor );
+ else
+ computeBackLayerColor( normal, L, viewDir, lightDiffuse, lightSpecular, materialIOR, aoFactor );
+ }
+ for ( int i=0 ; i < uNumAreaLights; ++i )
+ {
+ if (gl_FrontFacing)
+ computeFrontAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ else
+ computeBackAreaColor( i, arealights[i].diffuse, arealights[i].specular );
+ }
+
+ if ( 0.0 < alpha )
+ {
+ if (gl_FrontFacing)
+ computeFrontLayerEnvironment( normal, viewDir, aoFactor );
+ else
+ computeBackLayerEnvironment( normal, viewDir, aoFactor );
+ }
+
+ rgba += computeLayerWeights( alpha );
+
+#endif
diff --git a/res/effectlib/defaultMaterialBumpNoLod.glsllib b/res/effectlib/defaultMaterialBumpNoLod.glsllib
new file mode 100644
index 0000000..4144ae2
--- /dev/null
+++ b/res/effectlib/defaultMaterialBumpNoLod.glsllib
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float calcRGBAvg(in vec4 rgba)
+{
+ return (rgba.r + rgba.g + rgba.b) / 3.0;
+}
+
+vec3 defaultMaterialBumpNoLod(in sampler2D sampler, in float factor,
+ in vec2 texCoord, in vec3 tangent, in vec3 binormal,
+ in vec3 normal, in vec2 bumpSize)
+{
+ // invert factor
+ float invFactor = -factor;
+
+ vec2 unitStep = 1.0 / bumpSize;
+
+ float du = calcRGBAvg(texture2D(sampler, vec2(texCoord.x + unitStep.x, texCoord.y)))
+ - calcRGBAvg(texture2D(sampler, vec2(texCoord.x, texCoord.y)));
+ float dv = calcRGBAvg(texture2D(sampler, vec2(texCoord.x, texCoord.y + unitStep.y)))
+ - calcRGBAvg(texture2D(sampler, vec2(texCoord.x, texCoord.y)));
+
+ vec3 n = normalize(vec3(invFactor * du, invFactor * dv, 1.0));
+ n = n.x * normalize(tangent) + n.y * normalize(binormal) + n.z * normal;
+ return normalize(normal + n);
+}
diff --git a/res/effectlib/defaultMaterialFileBumpTexture.glsllib b/res/effectlib/defaultMaterialFileBumpTexture.glsllib
new file mode 100644
index 0000000..6901ace
--- /dev/null
+++ b/res/effectlib/defaultMaterialFileBumpTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** 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 QT3DS_DEFAULT_MATERIAL_FILE_BUMP_TEXTURE_GLSLLIB
+#define QT3DS_DEFAULT_MATERIAL_FILE_BUMP_TEXTURE_GLSLLIB
+
+#ifndef QT3DS_DEFINE_API
+#define QT3DS_DEFINE_API
+#endif
+
+#include "fileBumpTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/defaultMaterialFileDisplacementTexture.glsllib b/res/effectlib/defaultMaterialFileDisplacementTexture.glsllib
new file mode 100644
index 0000000..4c9af3f
--- /dev/null
+++ b/res/effectlib/defaultMaterialFileDisplacementTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** 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 QT3DS_DEFAULT_MATERIAL_FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+#define QT3DS_DEFAULT_MATERIAL_FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+
+#ifndef QT3DS_DEFINE_API
+#define QT3DS_DEFINE_API
+#endif
+
+#include "fileDisplacementTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/defaultMaterialFileNormalTexture.glsllib b/res/effectlib/defaultMaterialFileNormalTexture.glsllib
new file mode 100644
index 0000000..70ab52b
--- /dev/null
+++ b/res/effectlib/defaultMaterialFileNormalTexture.glsllib
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** 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 QT3DS_DEFAULT_MATERIAL_FILE_NORMAL_TEXTURE_GLSLLIB
+#define QT3DS_DEFAULT_MATERIAL_FILE_NORMAL_TEXTURE_GLSLLIB
+
+#ifndef QT3DS_DEFINE_API
+#define QT3DS_DEFINE_API
+#endif
+
+#include "tangentSpaceNormalTexture.glsllib"
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/defaultMaterialFresnel.glsllib b/res/effectlib/defaultMaterialFresnel.glsllib
new file mode 100644
index 0000000..e0eff4f
--- /dev/null
+++ b/res/effectlib/defaultMaterialFresnel.glsllib
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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 DEFAULT_MATERIAL_FRESNEL_GLSLLIB
+#define DEFAULT_MATERIAL_FRESNEL_GLSLLIB
+
+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 ratio = F + (1.0 - F) * pow(1.0 - VdotN, fresnelPower);
+
+ return ratio;
+}
+
+#endif
diff --git a/res/effectlib/defaultMaterialLighting.glsllib b/res/effectlib/defaultMaterialLighting.glsllib
new file mode 100644
index 0000000..e96a450
--- /dev/null
+++ b/res/effectlib/defaultMaterialLighting.glsllib
@@ -0,0 +1,80 @@
+/**
+ * UICViewer lighting equation implementations
+ */
+
+#ifndef DEFAULT_MATERIAL_LIGHTING
+#define DEFAULT_MATERIAL_LIGHTING
+
+#include "diffuseReflectionBSDF.glsllib"
+#include "luminance.glsllib"
+#include "specularBSDF.glsllib"
+
+#include "funccalculatePointLightAttenuation.glsllib"
+#include "funcgetTransformedUVCoords.glsllib"
+
+vec2 calculateLightParameters( vec3 lightDir, vec3 normalDir )
+{
+ vec2 retval;
+ retval.x = max( 0.0, -1.0 * dot( lightDir, normalDir ) ); //diffuseIntensity
+ retval.y = clamp( retval.x * 4.0, 0.0, 1.0 ); //selfShadowTerm
+ return retval;
+}
+vec2 calculateWrapLightParameters( vec3 lightDir, vec3 normalDir, float wrap )
+{
+ vec2 retval;
+ retval.x = max( 0.0, -1.0 * ((dot(lightDir, normalDir) + wrap)/ (1.0 + wrap)) ); //diffuseIntensity
+ retval.y = clamp( retval.x, 0.0, 1.0 ); //selfShadowTerm
+ return retval;
+}
+
+vec3 calculateDirectionalAddition( vec3 lightColor, vec2 lightParameters ) {
+ return ( lightColor * lightParameters.x * lightParameters.y );
+}
+
+vec3 calculateSpecularAddition( vec3 lightDir, vec3 normalDir, vec3 viewVec, vec3 lightSpecularColor, float specularAmount
+ , float specularRoughness, vec2 lightParameters )
+{
+ vec3 reflection = normalize( 2.0 * lightParameters.x * normalDir + lightDir );
+ return ( lightParameters.y * specularAmount * lightSpecularColor * pow( clamp( dot( reflection, viewVec ), 0.0, 1.0 ), specularRoughness ) );
+}
+
+float calculateDiffuseAreaFactors( in vec3 lightDir, in vec3 lightPos, in vec4 lightUp, in vec4 lightRt, in vec3 worldPos, out vec3 outDir )
+{
+ vec3 v0 = lightPos - (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v1 = lightPos - (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v2 = lightPos + (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v3 = lightPos + (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ v0 = normalize( v0 - worldPos ); v1 = normalize( v1 - worldPos );
+ v2 = normalize( v2 - worldPos ); v3 = normalize( v3 - worldPos );
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+ outDir = vec3( 0.0 );
+ outDir -= normalize(cross( v0, v1 )) * a01;
+ outDir -= normalize(cross( v1, v2 )) * a12;
+ outDir -= normalize(cross( v2, v3 )) * a23;
+ outDir -= normalize(cross( v3, v0 )) * a30;
+ float retVal = length(outDir) * 0.15915494309; // solid angle / 2*pi
+ outDir = -normalize(outDir);
+ retVal *= clamp( dot( worldPos-lightPos, lightDir), 0.0, 1.0 );
+ return retVal;
+}
+
+vec3 calculateSpecDirection( in vec3 lightDir, in vec3 lightPos, in vec4 lightUp, in vec4 lightRt, in vec3 worldPos, in vec3 worldNorm, in vec3 viewDir )
+{
+ vec3 reflDir = reflect(viewDir, worldNorm);
+ vec3 ldir = normalize( lightPos - worldPos );
+ if ( dot( ldir, lightDir ) > 0.0 ) { return vec3(0.0001); }
+ float t = (dot(lightDir, worldPos) - dot(lightDir, lightPos)) / dot(lightDir, reflDir);
+ if ( t < 0.0 ) { return vec3(0.0001); }
+ vec3 xsectPos = worldPos - t * reflDir;
+ float tx = dot( xsectPos - lightPos, lightRt.xyz );
+ float ty = dot( xsectPos - lightPos, lightUp.xyz );
+ tx = clamp(tx, -lightRt.w*0.5, lightRt.w*0.5);
+ ty = clamp(ty, -lightUp.w*0.5, lightUp.w*0.5);
+ xsectPos = lightPos + lightUp.xyz * ty + lightRt.xyz * tx;
+ return normalize( worldPos - xsectPos );
+}
+
+#endif
diff --git a/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib b/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib
new file mode 100644
index 0000000..1035e43
--- /dev/null
+++ b/res/effectlib/defaultMaterialPhysGlossyBSDF.glsllib
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** 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 DEFAULT_MATERIAL_PHYS_GLOSSY_BSDF_GLSLLIB
+#define DEFAULT_MATERIAL_PHYS_GLOSSY_BSDF_GLSLLIB
+#ifndef QT3DS_DEFINE_API
+#define QT3DS_DEFINE_API
+#endif
+
+#include "luminance.glsllib"
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+#include "physGlossyBSDF.glsllib"
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/depthpass.glsllib b/res/effectlib/depthpass.glsllib
new file mode 100644
index 0000000..cbd45c2
--- /dev/null
+++ b/res/effectlib/depthpass.glsllib
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 DEPTHPASS_GLSLIB
+#define DEPTHPASS_GLSLIB 1
+
+float calculateVertexDepth( vec2 camera_properties, vec4 position )
+{
+ float camera_range = camera_properties.y - camera_properties.x;
+ return 1.0 - ((position.w - camera_properties.x) / (camera_range));
+}
+
+#if __VERSION__ <= 120
+float modf(in float val, out float integer)
+{
+ integer = floor(val);
+ return val - integer;
+}
+#endif
+
+vec4 outputDepth( float vert_depth )
+{
+ float integer_portion = 0.0;
+ float fraction = modf((vert_depth * 255.0), integer_portion);
+ return vec4( integer_portion / 255.0, fraction, 0, 1.0 );
+}
+
+float getDepthValue( vec4 depth_texture_sample, vec2 camera_properties )
+{
+
+#if __VERSION__ >= 300
+ float zNear = camera_properties.x;
+ float zFar = camera_properties.y;
+ float zRange = zFar - zNear;
+ float z_b = depth_texture_sample.x;
+ float z_n = 2.0 * z_b - 1.0;
+ float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zRange));
+ return 1.0 - ((z_e - camera_properties.x) / (zRange));
+#else
+ return depth_texture_sample.x + (depth_texture_sample.y / 255.0);
+#endif
+}
+
+float depthValueToLinearDistance( float depth_value, vec2 camera_properties )
+{
+ float FarClipDistance = camera_properties.y;
+ float NearClipDistance = camera_properties.x;
+ float DepthRange = FarClipDistance - NearClipDistance;
+ float linearDepth = NearClipDistance + (DepthRange * (1.0 - depth_value));
+ return linearDepth;
+}
+
+#endif
diff --git a/res/effectlib/dfTint.glsllib b/res/effectlib/dfTint.glsllib
new file mode 100644
index 0000000..f1f4b7a
--- /dev/null
+++ b/res/effectlib/dfTint.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 dfTint( in vec3 tint, in vec4 base )
+{
+ return( vec4( tint * base.rgb, base.a ) );
+}
+
diff --git a/res/effectlib/diffuseReflectionBSDF.glsllib b/res/effectlib/diffuseReflectionBSDF.glsllib
new file mode 100644
index 0000000..a98509d
--- /dev/null
+++ b/res/effectlib/diffuseReflectionBSDF.glsllib
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "funcdiffuseReflectionBSDF.glsllib"
+#include "funcdiffuseReflectionWrapBSDF.glsllib"
+
+vec4 lambertReflectionBSDF( in vec3 N, in vec3 L, in vec3 lightDiffuse )
+{
+ // If we're not going to use the roughness on the diffuse, there's no point
+ // in wasting the cycles for the branching.
+ float cosThetaI = max( 0.0, dot( N, L ) );
+ return vec4( cosThetaI * lightDiffuse, 1.0 );
+}
+
+
+vec4 diffuseReflectionBSDFEnvironment( in vec3 N, in float roughness )
+{
+ return( vec4( 0.0, 0.0, 0.0, 1.0 ) );
+}
+
+// RNM radiosity normal maps
+vec4 diffuseRNM( in vec3 N, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+ // we use a fixed basis like Half Life
+ vec3 B0 = vec3( -0.40825, 0.70711, 0.57735);
+ vec3 B1 = vec3( -0.40825, -0.70711, 0.57735);
+ vec3 B2 = vec3( 0.8165, 0.0, 0.57735);
+
+ vec3 dp;
+ dp.x = clamp( dot ( N , B0 ), 0.0, 1.0);
+ dp.y = clamp( dot ( N , B1 ), 0.0, 1.0);
+ dp.z = clamp( dot ( N , B2 ), 0.0, 1.0);
+
+ float sum = 1.0 / dot( dp, vec3(1.0, 1.0, 1.0) );
+ vec3 diffuseLight = dp.x * rnmX + dp.y * rnmY + dp.z * rnmZ;
+ //vec3 diffuseLight = N.x * rnmX + N.y * rnmY + N.z * rnmZ;
+
+ return (vec4(diffuseLight, 1.0) * sum);
+}
diff --git a/res/effectlib/diffuseTransmissionBSDF.glsllib b/res/effectlib/diffuseTransmissionBSDF.glsllib
new file mode 100644
index 0000000..f6e5f52
--- /dev/null
+++ b/res/effectlib/diffuseTransmissionBSDF.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 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$
+**
+****************************************************************************/
+
+vec4 diffuseTransmissionBSDF( in vec3 N, in vec3 L, in vec3 viewDir, in vec3 lightDiffuse, in vec4 transmissiveColor, in float translucentFalloff, float lightWrap )
+{
+ float cosThetaI = max( 0.0, (dot( N, L ) + lightWrap) / (1.0 + lightWrap) );
+ float factor = cosThetaI;
+
+ float l = 0.2126 * transmissiveColor.r + 0.7152 * transmissiveColor.g + 0.0722 * transmissiveColor.b;
+
+ float translucent_thickness = l * l;
+ float translucent_thickness_exp = exp( translucent_thickness * translucentFalloff);
+
+ return( translucent_thickness_exp * vec4( factor * lightDiffuse, 1.0 ) );
+}
diff --git a/res/effectlib/directionalFactor.glsllib b/res/effectlib/directionalFactor.glsllib
new file mode 100644
index 0000000..78af883
--- /dev/null
+++ b/res/effectlib/directionalFactor.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 directionalFactor( in vec3 normal, in vec3 viewDir, in vec3 normal_col, in vec3 grazing_col, in float exponent, in vec4 base )
+{
+ float f;
+
+ f = clamp(dot(viewDir, normal),0.0, 1.0 );
+ f = 1.0 - pow(f, 1.0/exponent);
+ vec3 directionalColor = mix( normal_col, grazing_col, f );
+
+ vec4 color = base * vec4(directionalColor, 1.0);
+
+ return color;
+}
diff --git a/res/effectlib/distancefieldtext.frag b/res/effectlib/distancefieldtext.frag
new file mode 100644
index 0000000..1d83490
--- /dev/null
+++ b/res/effectlib/distancefieldtext.frag
@@ -0,0 +1,28 @@
+#ifdef GL_OES_standard_derivatives
+# extension GL_OES_standard_derivatives : enable
+#else
+# define use_fallback
+#endif
+
+varying highp vec2 sampleCoord;
+
+uniform sampler2D _qt_texture;
+uniform highp vec4 color;
+
+#ifdef use_fallback
+varying highp vec2 alphas;
+#endif
+
+void main()
+{
+ highp float distance = texture2D(_qt_texture, sampleCoord).a;
+
+#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);
+#endif
+
+ gl_FragColor = color * alpha;
+}
diff --git a/res/effectlib/distancefieldtext.vert b/res/effectlib/distancefieldtext.vert
new file mode 100644
index 0000000..f6b2de4
--- /dev/null
+++ b/res/effectlib/distancefieldtext.vert
@@ -0,0 +1,77 @@
+#ifdef GL_OES_standard_derivatives
+# extension GL_OES_standard_derivatives : enable
+#else
+# define use_fallback
+#endif
+
+uniform highp mat4 mvp;
+uniform highp float fontScale;
+uniform int textureWidth;
+uniform int textureHeight;
+
+attribute highp vec3 vCoord;
+attribute highp vec2 tCoord;
+
+varying highp vec2 sampleCoord;
+
+#ifdef use_fallback
+varying highp vec2 alphas;
+
+highp float thresholdFunc(highp float scale)
+{
+ highp float base = 0.5;
+ highp float baseDev = 0.065;
+ highp float devScaleMin = 0.15;
+ highp float devScaleMax = 0.3;
+ return base - ((clamp(scale, devScaleMin, devScaleMax) - devScaleMin)
+ / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+highp float spreadFunc(highp float scale)
+{
+ return 0.06 / scale;
+}
+
+highp vec2 alphaRange(highp float scale)
+{
+ highp float base = thresholdFunc(scale);
+ highp float range = spreadFunc(scale);
+ highp float alphaMin = max(0.0, base - range);
+ highp float alphaMax = min(base + range, 1.0);
+ return vec2(alphaMin, alphaMax);
+}
+
+highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int row0, int row1)
+{
+ return m[col0][row0] * m[col1][row1] - m[col0][row1] * m[col1][row0];
+}
+
+highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int col2,
+ int row0, int row1, int row2)
+{
+ highp float det = m[col0][row0] * determinantOfSubmatrix(m, col1, col2, row1, row2);
+ det -= m[col1][row0] * determinantOfSubmatrix(m, col0, col2, row1, row2);
+ det += m[col2][row0] * determinantOfSubmatrix(m, col0, col1, row1, row2);
+ return det;
+}
+
+highp float determinant(highp mat4 m)
+{
+ highp float det = m[0][0] * determinantOfSubmatrix(m, 1, 2, 3, 1, 2, 3);
+ det -= m[1][0] * determinantOfSubmatrix(m, 0, 2, 3, 1, 2, 3);
+ det += m[2][0] * determinantOfSubmatrix(m, 0, 1, 3, 1, 2, 3);
+ det -= m[3][0] * determinantOfSubmatrix(m, 0, 1, 2, 1, 2, 3);
+ return det;
+}
+#endif
+
+void main()
+{
+#ifdef use_fallback
+ highp float scale = fontScale * pow(abs(determinant(mvp)), 1.0 / 3.0);
+ alphas = alphaRange(scale);
+#endif
+
+ sampleCoord = tCoord * vec2(1.0 / float(textureWidth), 1.0 / float(textureHeight));
+ gl_Position = mvp * vec4(vCoord, 1.0);
+}
diff --git a/res/effectlib/distancefieldtext_core.frag b/res/effectlib/distancefieldtext_core.frag
new file mode 100644
index 0000000..f11dcc1
--- /dev/null
+++ b/res/effectlib/distancefieldtext_core.frag
@@ -0,0 +1,11 @@
+in vec2 sampleCoord;
+
+uniform sampler2D _qt_texture;
+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);
+}
diff --git a/res/effectlib/distancefieldtext_core.vert b/res/effectlib/distancefieldtext_core.vert
new file mode 100644
index 0000000..2dc198f
--- /dev/null
+++ b/res/effectlib/distancefieldtext_core.vert
@@ -0,0 +1,15 @@
+in vec3 vCoord;
+in vec2 tCoord;
+
+out vec2 sampleCoord;
+
+uniform mat4 mvp;
+uniform int textureWidth;
+uniform int textureHeight;
+uniform float fontScale;
+
+void main()
+{
+ sampleCoord = tCoord * vec2(1.0 / float(textureWidth), 1.0 / float(textureHeight));
+ gl_Position = mvp * vec4(vCoord, 1.0);
+}
diff --git a/res/effectlib/distancefieldtext_dropshadow.frag b/res/effectlib/distancefieldtext_dropshadow.frag
new file mode 100644
index 0000000..fdb68ba
--- /dev/null
+++ b/res/effectlib/distancefieldtext_dropshadow.frag
@@ -0,0 +1,47 @@
+#ifdef GL_OES_standard_derivatives
+# extension GL_OES_standard_derivatives : enable
+#else
+# define use_fallback
+#endif
+
+varying highp vec2 sampleCoord;
+varying highp vec2 shadowSampleCoord;
+varying highp vec4 normalizedTextureBounds;
+
+#ifdef use_fallback
+varying highp vec2 alphas;
+#endif
+
+uniform sampler2D _qt_texture;
+uniform highp vec4 color;
+uniform highp vec4 shadowColor;
+
+void main()
+{
+ highp float shadowDistance = texture2D(_qt_texture,
+ clamp(shadowSampleCoord,
+ normalizedTextureBounds.xy,
+ normalizedTextureBounds.zw)).a;
+#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);
+#endif
+
+ highp vec4 shadowPixel = color * shadowColor * shadowAlpha;
+
+ highp float textDistance = texture2D(_qt_texture,
+ clamp(sampleCoord,
+ normalizedTextureBounds.xy,
+ normalizedTextureBounds.zw)).a;
+#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);
+#endif
+
+ highp vec4 textPixel = color * textAlpha;
+ gl_FragColor = mix(shadowPixel, textPixel, textPixel.a);
+}
diff --git a/res/effectlib/distancefieldtext_dropshadow.vert b/res/effectlib/distancefieldtext_dropshadow.vert
new file mode 100644
index 0000000..5939a8c
--- /dev/null
+++ b/res/effectlib/distancefieldtext_dropshadow.vert
@@ -0,0 +1,88 @@
+#ifdef GL_OES_standard_derivatives
+# extension GL_OES_standard_derivatives : enable
+#else
+# define use_fallback
+#endif
+
+uniform highp mat4 mvp;
+uniform highp float fontScale;
+uniform int textureWidth;
+uniform int textureHeight;
+uniform highp vec2 shadowOffset;
+
+attribute highp vec3 vCoord;
+attribute highp vec2 tCoord;
+attribute highp vec4 textureBounds;
+
+varying highp vec2 sampleCoord;
+varying highp vec2 shadowSampleCoord;
+varying highp vec4 normalizedTextureBounds;
+
+#ifdef use_fallback
+varying highp vec2 alphas;
+
+highp float thresholdFunc(highp float scale)
+{
+ highp float base = 0.5;
+ highp float baseDev = 0.065;
+ highp float devScaleMin = 0.15;
+ highp float devScaleMax = 0.3;
+ return base - ((clamp(scale, devScaleMin, devScaleMax) - devScaleMin)
+ / (devScaleMax - devScaleMin) * -baseDev + baseDev);
+}
+
+highp float spreadFunc(highp float scale)
+{
+ return 0.06 / scale;
+}
+
+highp vec2 alphaRange(highp float scale)
+{
+ highp float base = thresholdFunc(scale);
+ highp float range = spreadFunc(scale);
+ highp float alphaMin = max(0.0, base - range);
+ highp float alphaMax = min(base + range, 1.0);
+ return vec2(alphaMin, alphaMax);
+}
+
+highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int row0, int row1)
+{
+ return m[col0][row0] * m[col1][row1] - m[col0][row1] * m[col1][row0];
+}
+
+highp float determinantOfSubmatrix(highp mat4 m, int col0, int col1, int col2,
+ int row0, int row1, int row2)
+{
+ highp float det = m[col0][row0] * determinantOfSubmatrix(m, col1, col2, row1, row2);
+ det -= m[col1][row0] * determinantOfSubmatrix(m, col0, col2, row1, row2);
+ det += m[col2][row0] * determinantOfSubmatrix(m, col0, col1, row1, row2);
+ return det;
+}
+
+highp float determinant(highp mat4 m)
+{
+ highp float det = m[0][0] * determinantOfSubmatrix(m, 1, 2, 3, 1, 2, 3);
+ det -= m[1][0] * determinantOfSubmatrix(m, 0, 2, 3, 1, 2, 3);
+ det += m[2][0] * determinantOfSubmatrix(m, 0, 1, 3, 1, 2, 3);
+ det -= m[3][0] * determinantOfSubmatrix(m, 0, 1, 2, 1, 2, 3);
+ return det;
+}
+#endif
+
+void main()
+{
+#ifdef use_fallback
+ highp float scale = fontScale * pow(abs(determinant(mvp)), 1.0 / 3.0);
+ alphas = alphaRange(scale);
+#endif
+
+ highp vec2 textureSizeMultiplier = vec2(1.0 / float(textureWidth),
+ 1.0 / float(textureHeight));
+
+ sampleCoord = tCoord * textureSizeMultiplier;
+ shadowSampleCoord = (tCoord - shadowOffset) * textureSizeMultiplier;
+ normalizedTextureBounds = vec4(textureBounds.xy * textureSizeMultiplier,
+ textureBounds.zw * textureSizeMultiplier);
+
+ gl_Position = mvp * vec4(vCoord, 1.0);
+}
diff --git a/res/effectlib/distancefieldtext_dropshadow_core.frag b/res/effectlib/distancefieldtext_dropshadow_core.frag
new file mode 100644
index 0000000..e13182e
--- /dev/null
+++ b/res/effectlib/distancefieldtext_dropshadow_core.frag
@@ -0,0 +1,28 @@
+in vec2 sampleCoord;
+in vec2 shadowSampleCoord;
+in vec4 normalizedTextureBounds;
+
+uniform sampler2D _qt_texture;
+uniform vec4 color;
+uniform vec4 shadowColor;
+
+void main()
+{
+ float shadowDistance = texture(_qt_texture,
+ clamp(shadowSampleCoord,
+ normalizedTextureBounds.xy,
+ normalizedTextureBounds.zw)).r;
+ float shadowDistanceD = fwidth(shadowDistance);
+ float shadowAlpha = smoothstep(0.5 - shadowDistanceD, 0.5, 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);
+ vec4 textPixel = color * textAlpha;
+
+ fragOutput = mix(shadowPixel, textPixel, textPixel.a);
+}
diff --git a/res/effectlib/distancefieldtext_dropshadow_core.vert b/res/effectlib/distancefieldtext_dropshadow_core.vert
new file mode 100644
index 0000000..7d9736e
--- /dev/null
+++ b/res/effectlib/distancefieldtext_dropshadow_core.vert
@@ -0,0 +1,25 @@
+in vec3 vCoord;
+in vec2 tCoord;
+in vec4 textureBounds;
+
+out vec2 sampleCoord;
+out vec2 shadowSampleCoord;
+
+out vec4 normalizedTextureBounds;
+
+uniform mat4 mvp;
+uniform int textureWidth;
+uniform int textureHeight;
+uniform float fontScale;
+uniform vec2 shadowOffset;
+
+void main()
+{
+ vec2 textureSizeMultiplier = vec2(1.0 / float(textureWidth), 1.0 / float(textureHeight));
+
+ sampleCoord = tCoord * textureSizeMultiplier;
+ shadowSampleCoord = (tCoord - shadowOffset) * textureSizeMultiplier;
+ normalizedTextureBounds = vec4(textureBounds.xy * textureSizeMultiplier,
+ textureBounds.zw * textureSizeMultiplier);
+ gl_Position = mvp * vec4(vCoord, 1.0);
+}
diff --git a/res/effectlib/effect.glsllib b/res/effectlib/effect.glsllib
new file mode 100644
index 0000000..802a846
--- /dev/null
+++ b/res/effectlib/effect.glsllib
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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 EFFECT_GLSLLIB
+#define EFFECT_GLSLLIB 1
+
+//Defines used in the effect files.
+
+vec4 GetTextureValue( sampler2D sampler, vec2 inUVCoords, float inTextureAlphaInfo )
+{
+ vec4 c = texture2D(sampler, inUVCoords);
+ c.rgb = mix( c.rgb*c.a, c.rgb, inTextureAlphaInfo );
+ return c;
+}
+
+vec4 GetTextureValuePreMult( sampler2D sampler, vec2 inUVCoords )
+{
+ return texture2D(sampler, inUVCoords);
+}
+
+#define SNAPPER_TITLE( title )
+
+#define SNAPPER_PARAMETER(propName, datatype, rangeMin, rangeMax, propNiceName, defaultValue) datatype propName
+
+#define SNAPPER_ANGLE( propName, propNiceName, defaultValueAsFloat ) uniform float propName;
+#define SNAPPER_CHECKBOX(propName, propNiceName, defaultValue) uniform float propName;
+
+#define SNAPPER_ENUM_BEGIN(propName, propNiceName, defaultValueAsIndex) uniform int propName;
+#define SNAPPER_ENUM_VALUE(valueNiceName)
+#define SNAPPER_ENUM_END()
+
+#define SNAPPER_POINT2(propName, propNiceName, defaultValue) uniform vec2 propName;
+#define SNAPPER_COLOR(propName, propNiceName, defaultValue) uniform vec3 propName;
+
+
+#define TEXTURE_LOOKUP_FUNC(name) \
+
+
+//texType = one of: ubyte, ushort, float
+//texFormat = one of: rgb, rgba, lum, lum_alpha
+//texFilter = one of: nearest, linear
+//texWrap = one of: repeat, clamp
+#define SNAPPER_EXTERNAL_PARAMETER(propName, datatype, rangeMin, rangeMax, propNiceName, defaultValue)
+#define SNAPPER_EXTERNAL_ANGLE(propName, propNiceName, defaultValueAsFloat)
+
+// Provide the ability to render outside a effect boundary.
+// Total size = The original effect size * Overrendering value
+// Overrendering value needs to be >= 1.0
+#define SNAPPER_OVERRENDERING(value) const float OverrenderingValue = value;
+
+
+
+#ifdef VERTEX_SHADER
+// Attributes and uniforms used throughout the system.
+attribute vec3 attr_pos;
+attribute vec2 attr_uv;
+#endif
+
+uniform mat4 ModelViewProjectionMatrix;
+//x holds the texture width, y holds the texture height
+//z holds 0,1 value if it should be premultiplied
+uniform vec4 Texture0Info;
+uniform vec2 DestSize; //size of the destination in pixels including overrendering if specified.
+uniform sampler2D Texture0;
+varying vec2 TexCoord;
+uniform vec2 FragColorAlphaSettings; //x > 0.0 premultiply result, y is an alpha multiplier (opacity setting)
+
+vec4 Transform( mat4 ModelViewProjectionMatrix, vec2 inDestSize, vec4 inVertex )
+{
+ vec4 temp = ModelViewProjectionMatrix * vec4( inDestSize.x * .5 * inVertex.x, inDestSize.y * .5 * inVertex.y, inVertex.z, inVertex.w );
+ return temp;
+}
+////////////////////////////////////////////////////////////
+// provide the texture lookup functions for the default
+// texture (Texture0).
+vec4 texture2D_0(vec2 uv)
+{
+ return GetTextureValue( Texture0, uv, Texture0Info.z );
+}
+
+#ifdef FRAGMENT_SHADER
+////////////////////////////////////////////////////////////
+// the functions to set the final frag result.
+void colorOutput(vec4 c)
+{
+ c *= FragColorAlphaSettings.x;
+ gl_FragColor = clamp(c, 0.0, c.a );
+}
+
+#endif
+
+
+
+////////////////////////////////////////////////////////////
+// define the main functions.
+
+#ifdef VERTEX_SHADER
+#ifndef NO_VERT_MAIN
+
+void vert();
+void main()
+{
+ gl_Position = Transform( ModelViewProjectionMatrix, DestSize, vec4(attr_pos, 1.0) );
+ TexCoord = attr_uv;
+ vert();
+}
+
+#endif
+#endif
+
+#ifdef FRAGMENT_SHADER
+#ifndef NO_FRAG_MAIN
+void frag();
+void main()
+{
+ frag();
+}
+#endif // NO_FRAG_MAIN
+#endif // FRAGMENT_SHADER
+
+#endif // EFFECT_GLSLLIB
diff --git a/res/effectlib/evalBakedShadowMap.glsllib b/res/effectlib/evalBakedShadowMap.glsllib
new file mode 100644
index 0000000..a283d8a
--- /dev/null
+++ b/res/effectlib/evalBakedShadowMap.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 evalBakedShadowMap( in vec3 inCoords )
+{
+ vec4 shadowCol = (uShadowMappingEnabled) ? texture( uBakedShadowTexture, inCoords.xy ) : vec4( 1.0, 1.0, 1.0, 1.0 );
+
+ return shadowCol;
+}
diff --git a/res/effectlib/evalEnvironmentMap.glsllib b/res/effectlib/evalEnvironmentMap.glsllib
new file mode 100644
index 0000000..18431c7
--- /dev/null
+++ b/res/effectlib/evalEnvironmentMap.glsllib
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec3 evalEnvironmentMap( in vec3 R, float roughness )
+{
+ // convert R to spherical texture coordinates
+ vec2 tc = vec2( ( atan( R.x, -R.z ) + PI ) / ( PI_TWO ), acos( -R.y ) / PI );
+
+ vec2 envMapSize = vec2( textureSize( uEnvironmentTexture, 0 ) );
+ float envMapLevels = log2( max( envMapSize.x, envMapSize.y ) );
+
+ // simulate textureQueryLod
+ vec2 dx = dFdx( tc * envMapSize.x );
+ vec2 dy = dFdy( tc * envMapSize.y );
+
+ float px = dot( dx, dx );
+ float py = dot( dy, dy );
+
+ float maxlod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
+ float minlod = 0.5 * log2( min( px, py ) );
+
+ //float lod = max(0.0, maxlod - min( maxlod - minlod, envMapLevels ));
+ float lod = max(0.0, min( minlod, envMapLevels ));
+
+ float roughLevel = mix( lod , envMapLevels, roughness );
+
+ return( textureLod( uEnvironmentTexture, tc, roughLevel ).rgb );
+}
diff --git a/res/effectlib/evalLightmaps.glsllib b/res/effectlib/evalLightmaps.glsllib
new file mode 100644
index 0000000..1a9bc99
--- /dev/null
+++ b/res/effectlib/evalLightmaps.glsllib
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 evalLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ vec3 uTransform = vec3(rotScale.x, rotScale.y, offset.x);
+ vec3 vTransform = vec3(rotScale.z, rotScale.w, offset.y);
+
+ vec2 transfCoord = vec2( dot( uTransform, inCoords ), dot( vTransform, inCoords ) );
+
+ vec4 value = texture( sampler, transfCoord.xy);
+
+ return value;
+}
+
+vec4 evalIndirectLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+}
+
+vec4 evalRadiosityLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+}
+
+vec4 evalShadowLightmap( in sampler2D sampler, in vec3 inCoords, in vec4 rotScale, in vec3 offset )
+{
+ return evalLightmap( sampler, inCoords, rotScale, offset );
+} \ No newline at end of file
diff --git a/res/effectlib/fileBumpTexture.glsllib b/res/effectlib/fileBumpTexture.glsllib
new file mode 100644
index 0000000..d0129a8
--- /dev/null
+++ b/res/effectlib/fileBumpTexture.glsllib
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** 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 FILE_BUMP_TEXTURE_GLSLLIB
+#define FILE_BUMP_TEXTURE_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+// compute a normal based on a heightfield style bump texture
+// example call:
+// 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 );
+
+
+
+vec3 fileBumpTexture( in sampler2D sampler, in float factor, in int bumpSource
+ , in texture_coordinate_info uvw
+ , in vec2 cropU, in vec2 cropV
+ , in int wrapU, in int wrapV, in vec3 normal )
+{
+ vec2 bumpMapSize = vec2( textureSize( sampler, 0 ) );
+ float bumpMapLevels = log2( max( bumpMapSize.x, bumpMapSize.y ) );
+ // simulate textureQueryLod
+ vec2 dx = dFdx( uvw.position.xy * bumpMapSize.x );
+ vec2 dy = dFdy( uvw.position.xy * bumpMapSize.y );
+
+ float px = dot( dx, dx );
+ float py = dot( dy, dy );
+
+ float maxlod = 0.5 * log2( max( px, py ) ); // log2(sqrt()) = 0.5*log2()
+ float minlod = 0.5 * log2( min( px, py ) );
+
+ float lod = max(0.0, min( maxlod, bumpMapLevels ));
+
+ // invert factor
+ float invFactor = -factor;
+
+ // currently no lod supported we use 3.3 GL
+ //float lod = textureQueryLod( sampler, uvw.position.xy ).x;
+ vec2 size = mix( vec2( textureSize( sampler, int( floor( lod ) ) ) ), vec2( textureSize( sampler, int( ceil( lod ) ) ) ), fract( lod ) );
+ vec2 unitStep = 1.0 / size;
+
+ // Add an inveres scale to keep the original gradient values
+ // this makes the bumps a lot smoother.
+ // Or we could do it like in iRay and sample always at original size.
+ // But this makes me feel better.
+ vec2 scale = size / bumpMapSize;
+
+ float du = monoChannel( textureLod( sampler, vec2( uvw.position.x + unitStep.x, uvw.position.y ), lod ), bumpSource )
+ - monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y ), lod ), bumpSource );
+ float dv = monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y + unitStep.y ), lod ), bumpSource )
+ - monoChannel( textureLod( sampler, vec2( uvw.position.x, uvw.position.y ), lod ), bumpSource );
+
+
+ vec3 n = normalize(vec3(invFactor * scale.x * du, invFactor * scale.x * dv, 1.0));
+ n = n.x*uvw.tangent_u + n.y*uvw.tangent_v + n.z*normal;
+ return normalize(normal + n);
+}
+
+#include "textureCoordinateInfo.glsllib"
+
+//Simpler version built to run from UIC image data
+//In our case, we have already generated the texture coordinate x,y position
+//TODO - figure out if we need to manipulate tangent_u, tangent_v.
+vec3 simplerFileBumpTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal, vec3 normal )
+{
+ return fileBumpTexture( sampler, factor, mono_average
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal )
+ , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+ , wrap_repeat, wrap_repeat, normal );
+}
+
+
+#endif
diff --git a/res/effectlib/fileDisplacementTexture.glsllib b/res/effectlib/fileDisplacementTexture.glsllib
new file mode 100644
index 0000000..a38d701
--- /dev/null
+++ b/res/effectlib/fileDisplacementTexture.glsllib
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+#define FILE_DISPLACEMENT_TEXTURE_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+
+vec3 fileDisplacementTexture( in sampler2D sampler, in float factor, in int displaceSource
+ , in texture_coordinate_info uvw, in vec3 normal, in vec3 pos )
+{
+ // compute displace factor
+ float df = monoChannel( texture( sampler, uvw.position.xy ), displaceSource );
+
+ return( normal * df * factor + pos );
+}
+
+
+//default material path version
+vec3 defaultMaterialFileDisplacementTexture( in sampler2D sampler, in float factor, vec2 texCoord, in vec3 normal, vec3 pos )
+{
+ return fileDisplacementTexture( sampler, factor, mono_luminance
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0) )
+ , normal, pos );
+}
+
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/fileTexture.glsllib b/res/effectlib/fileTexture.glsllib
new file mode 100644
index 0000000..6b9f6ab
--- /dev/null
+++ b/res/effectlib/fileTexture.glsllib
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+texture_return fileTexture( in sampler2D sampler, in vec3 colorOffset, in vec3 colorScale, in int monoSource, in texture_coordinate_info uvw
+ , in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV, in int gammaMode )
+{
+ vec4 t4 = texture( sampler, uvw.position.xy );
+ vec3 t3 = colorOffset + colorScale * t4.xyz;
+
+ // When we want to operate in linear color space uncomment the lines
+ if ( gammaMode == gamma_srgb )
+ {
+ t3 = pow( t3, vec3( 2.2 ) );
+ }
+
+ texture_return tr;
+ tr.tint = t3;
+ tr.mono = monoChannel( vec4( t3, t4.w ), monoSource );
+ return( tr );
+}
+
diff --git a/res/effectlib/flakeNoiseBumpTexture.glsllib b/res/effectlib/flakeNoiseBumpTexture.glsllib
new file mode 100644
index 0000000..e8e427c
--- /dev/null
+++ b/res/effectlib/flakeNoiseBumpTexture.glsllib
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec3 flakeNoiseBumpTexture( in texture_coordinate_info uvw, in float scale, in float strength, in vec3 normal )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0 * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ grad = miNoise( round( tex ) ).xyz;
+
+ vec3 n = normalize(vec3(strength * grad.x, strength * grad.y, 1.0));
+ n = n.x*uvw.tangent_u + n.y*uvw.tangent_v + n.z*normal;
+ return normalize(normal + n);
+}
+
diff --git a/res/effectlib/flakeNoiseTexture.glsllib b/res/effectlib/flakeNoiseTexture.glsllib
new file mode 100644
index 0000000..92f15d3
--- /dev/null
+++ b/res/effectlib/flakeNoiseTexture.glsllib
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+texture_return flakeNoiseTexture( in texture_coordinate_info uvw, in float intensity, in float scale, in float density )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0 * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ vec4 noise = miNoise( floor( tex ) );
+ float s = pow( noise.w, 1.0 / density ) * intensity;
+
+ texture_return tr;
+ tr.tint = vec3( noise.x, noise.y, noise.z );
+ tr.mono = clamp(s, 0.0, 1.0);
+ return( tr );
+}
+
+
+texture_return flakeNoiseAndBumpTexture( in texture_coordinate_info uvw, in float scale, in float intensity, in float density, float strength, in vec3 normal )
+{
+ vec3 tex = uvw.position / scale;
+ vec3 grad = miNoise( tex ).xyz;
+
+ // displace coordinate according to noise value
+ tex += 2.0 * grad;
+
+ // then use only integer coordinates, to make flakes transients harder and not wobbly
+ vec4 noise = miNoise( round( tex ) );
+ float s = pow( noise.w, 1.0 / density ) * intensity;
+
+ texture_return tr;
+ tr.tint = normalize( normal/strength + ( uvw.tangent_u * grad.x + uvw.tangent_v * grad.y + normal * abs( grad.z ) ) );
+ tr.mono = s;
+ return( tr );
+}
diff --git a/res/effectlib/fresnelLayer.glsllib b/res/effectlib/fresnelLayer.glsllib
new file mode 100644
index 0000000..60d7176
--- /dev/null
+++ b/res/effectlib/fresnelLayer.glsllib
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+
+float simpleFresnel( in vec3 N, in float ior, float fresnelPower )
+{
+ float F = ((1.0-ior) * (1.0-ior)) / ((1.0+ior) * (1.0+ior));
+ float fresnelGlancingAngle = clamp( 1.0 - dot(viewDir, N), 0.0, 1.0 );
+ float ratio = F + (1.0 - F) * pow(fresnelGlancingAngle, fresnelPower);
+
+ return ratio;
+}
+
+// PKC : A variation on the simple Schlick approach that also handles the characteristic
+// "dip" that metals exhibit. The dip is very mild or virtually nonexisting in dielectrics,
+// but shows up in metals because of their strong incident reflectivity, and also allows for
+// colored metals like gold or copper to show their Fresnel hue shift as well because certain
+// components will have different baseline responses.
+vec3 pseudoFresnel( in vec3 N, in vec3 ior, float fresnelPower )
+{
+ vec3 F0 = ((vec3(1.0)-ior) * (vec3(1.0)-ior)) / ((vec3(1.0)+ior) * (vec3(1.0)+ior));
+
+ float fresnelGlancingAngle = clamp( 1.0 - dot(viewDir, N), 0.0, 1.0 );
+
+ float fresCurve = pow(fresnelGlancingAngle, fresnelPower);
+ vec3 dipCurve = F0 * sin( 3.1415926535 * fresCurve ) * 0.31830988618;
+
+ vec3 retCol = (vec3(1.0) - F0) * fresCurve;
+ retCol += F0 - dipCurve;
+ return clamp(retCol, 0.0, 1.0);
+}
+
+// look here: http://en.wikipedia.org/wiki/Fresnel_equations
+float fresnel( in float eta1, in float eta2, in float cosTheta1 )
+{
+ float etaInv = eta1 / eta2;
+ float cosTheta2 = 1.0 - ( 1.0 - cosTheta1 * cosTheta1 ) * ( etaInv * etaInv );
+ if ( 0.0 <= cosTheta2 )
+ {
+ cosTheta2 = sqrt( cosTheta2 );
+ float n1t1 = eta1 * cosTheta1;
+ float n1t2 = eta1 * cosTheta2;
+ float n2t1 = eta2 * cosTheta1;
+ float n2t2 = eta2 * cosTheta2;
+ float rs = ( n1t1 - n2t2 ) / ( n1t1 + n2t2 );
+ float rp = ( n1t2 - n2t1 ) / ( n1t2 + n2t1 );
+ float f = 0.5 * ( rs * rs + rp * rp );
+ return( clamp( f, 0.0, 1.0 ) );
+ }
+ else
+ {
+ return( 1.0 );
+ }
+}
+
+// we assume, light rays run through air with ior == 1.0
+// with eta = eta2 / eta1, we have
+// - when hitting a front face: eta2 == ior, eta1 == 1.0 => eta = ior
+// - when hitting a back face : eta2 == 1.0, eta1 == ior => eta = 1.0 / ior
+vec3 fresnel( in vec3 N, in vec3 ior )
+{
+ float cosTheta1 = dot( N, viewDir );
+ if ( gl_FrontFacing )
+ {
+ return( vec3( fresnel( 1.0, ior[0], cosTheta1 ), fresnel( 1.0, ior[1], cosTheta1 ), fresnel( 1.0, ior[2], cosTheta1 ) ) );
+ }
+ else
+ {
+ return( vec3( fresnel( ior[0], 1.0, cosTheta1 ), fresnel( ior[1], 1.0, cosTheta1 ), fresnel( ior[2], 1.0, cosTheta1 ) ) );
+ }
+}
+
+vec4 fresnelLayer( in vec3 N, in vec3 ior, in float weight, in vec3 layercolor, in vec4 layer, in vec4 base, in float alpha )
+{
+ vec3 refl = reflect( -viewDir, N );
+ float reflWt = clamp( dot( surfNormal, refl ) + 1.0, 0.0, 1.0 );
+
+ vec3 fresColor = reflWt * weight * layercolor * pseudoFresnel( N, ior, 5.0 );
+
+ return( vec4( mix( base.rgb, layer.rgb, fresColor ), mix(alpha, 1.0, luminance(fresColor)) ) );
+}
+
diff --git a/res/effectlib/funcareaLightVars.glsllib b/res/effectlib/funcareaLightVars.glsllib
new file mode 100644
index 0000000..7505b34
--- /dev/null
+++ b/res/effectlib/funcareaLightVars.glsllib
@@ -0,0 +1,32 @@
+#define MAX_AREA_LIGHTS 16
+
+// note this struct must exactly match the memory layout of the
+// struct SLightSourceShader in the source code. If you make changes here you need
+// to adjust the struct SLightSourceShader as well
+struct AreaLight
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+layout (std140) uniform cbBufferAreaLights
+{
+ int uNumAreaLights;
+ AreaLight arealights[MAX_AREA_LIGHTS];
+};
diff --git a/res/effectlib/funccalculateDiffuseAreaOld.glsllib b/res/effectlib/funccalculateDiffuseAreaOld.glsllib
new file mode 100644
index 0000000..fc37390
--- /dev/null
+++ b/res/effectlib/funccalculateDiffuseAreaOld.glsllib
@@ -0,0 +1,29 @@
+float calculateDiffuseAreaOld(in vec3 lightDir, in vec3 lightPos, in vec4 lightUp,
+ in vec4 lightRt, in vec3 worldPos, out vec3 outDir)
+{
+ if ( dot( worldPos-lightPos, lightDir) < 0.0 )
+ return 0.0;
+
+ vec3 v0 = lightPos - (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v1 = lightPos - (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v2 = lightPos + (lightRt.xyz * lightRt.w * 0.5) + (lightUp.xyz * lightUp.w * 0.5);
+ vec3 v3 = lightPos + (lightRt.xyz * lightRt.w * 0.5) - (lightUp.xyz * lightUp.w * 0.5);
+ v0 = normalize( v0 - worldPos ); v1 = normalize( v1 - worldPos );
+ v2 = normalize( v2 - worldPos ); v3 = normalize( v3 - worldPos );
+
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+
+ outDir = vec3( 0.0 );
+ outDir -= normalize(cross( v0, v1 )) * a01;
+ outDir -= normalize(cross( v1, v2 )) * a12;
+ outDir -= normalize(cross( v2, v3 )) * a23;
+ outDir -= normalize(cross( v3, v0 )) * a30;
+
+ float retVal = length(outDir) * 0.15915494309; // solid angle / 2*pi
+ outDir = normalize(outDir);
+ retVal *= clamp( dot( worldPos-lightPos, lightDir), 0.0, 1.0 );
+ return retVal;
+}
diff --git a/res/effectlib/funccalculatePointLightAttenuation.glsllib b/res/effectlib/funccalculatePointLightAttenuation.glsllib
new file mode 100644
index 0000000..5f42162
--- /dev/null
+++ b/res/effectlib/funccalculatePointLightAttenuation.glsllib
@@ -0,0 +1,4 @@
+float calculatePointLightAttenuation(vec3 attenuationConstants, float lightDistance ) {
+ return 1.0 / (attenuationConstants.x + attenuationConstants.y * lightDistance
+ + attenuationConstants.z * lightDistance * lightDistance);
+}
diff --git a/res/effectlib/funccomputeMicroHit.glsllib b/res/effectlib/funccomputeMicroHit.glsllib
new file mode 100644
index 0000000..7c52691
--- /dev/null
+++ b/res/effectlib/funccomputeMicroHit.glsllib
@@ -0,0 +1,50 @@
+bool rayToLightUV( in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 rayDir, out vec2 uv )
+{
+ float d0 = dot( lightPos, lightFrame[2] );
+ float d1 = dot( pos, lightFrame[2] );
+ float fac = dot( rayDir, lightFrame[2] );
+
+ if ((d0 < d1) || ( fac < 0.001 ))
+ {
+ uv = vec2(-1.0);
+ return false;
+ }
+
+ float t = (d0 - d1) / fac;
+ vec3 hitPos = pos + t * rayDir;
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ hitPos -= lightPos;
+ uv.x = ( dot(hitPos, lightFrame[0]) / width ) + 0.5;
+ uv.y = ( dot(hitPos, lightFrame[1]) / height ) + 0.5;
+ return true;
+}
+
+float computeMicroHit( in vec3 pos, in mat3 tanFrame, in vec3 lightPos, in mat3 lightFrame, in float width, in float height, in vec3 viewDir, out vec2 UV[5] )
+{
+ vec3 rayDir = reflect( -viewDir, tanFrame[2] );
+ vec2 ctrUV;
+ bool isHit = rayToLightUV( pos, lightFrame, lightPos, width, height, rayDir, ctrUV );
+ if ((!isHit) || ( dot(rayDir, tanFrame[2]) < 0.001 )) { return 0.0; }
+
+ vec3 H0 = 0.99749686716 * tanFrame[2] + 0.005 * tanFrame[0];
+ vec3 H1 = 0.99749686716 * tanFrame[2] - 0.005 * tanFrame[0];
+ vec3 H2 = 0.99749686716 * tanFrame[2] + 0.005 * tanFrame[1];
+ vec3 H3 = 0.99749686716 * tanFrame[2] - 0.005 * tanFrame[1];
+
+ vec3 R[4];
+ R[0] = reflect( -viewDir, H0 );
+ R[1] = reflect( -viewDir, H1 );
+ R[2] = reflect( -viewDir, H2 );
+ R[3] = reflect( -viewDir, H3 );
+
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[0], UV[0] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[1], UV[1] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[2], UV[2] );
+ rayToLightUV( pos, lightFrame, lightPos, width, height, R[3], UV[3] );
+
+ UV[4] = ctrUV;
+
+ return clamp( dot(rayDir, tanFrame[2]), 0.0, 1.0 );
+}
diff --git a/res/effectlib/funcdiffuseReflectionBSDF.glsllib b/res/effectlib/funcdiffuseReflectionBSDF.glsllib
new file mode 100644
index 0000000..bda0ea6
--- /dev/null
+++ b/res/effectlib/funcdiffuseReflectionBSDF.glsllib
@@ -0,0 +1,43 @@
+#ifndef PI
+#define PI 3.14159265358979
+#define PI_SQUARE ( PI * PI )
+#endif
+
+vec4 diffuseReflectionBSDF(in vec3 N, in vec3 L, in vec3 viewDir,
+ in vec3 lightDiffuse, in float roughness)
+{
+ 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 ) );
+}
diff --git a/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib b/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib
new file mode 100644
index 0000000..9afc58b
--- /dev/null
+++ b/res/effectlib/funcdiffuseReflectionWrapBSDF.glsllib
@@ -0,0 +1,5 @@
+vec4 diffuseReflectionWrapBSDF(vec3 normalDir, in vec3 L, in vec3 lightDiffuse, float wrap)
+{
+ float I = max( 0.0, ((dot(L, normalDir) + wrap)/ (1.0 + wrap)) ); //diffuseIntensity
+ return vec4( I * lightDiffuse, 1.0 );
+}
diff --git a/res/effectlib/funcgetTransformedUVCoords.glsllib b/res/effectlib/funcgetTransformedUVCoords.glsllib
new file mode 100644
index 0000000..9b14a28
--- /dev/null
+++ b/res/effectlib/funcgetTransformedUVCoords.glsllib
@@ -0,0 +1,4 @@
+vec2 getTransformedUVCoords( vec3 inCoords, vec3 inUTransform, vec3 inVTransform )
+{
+ return vec2( dot( inUTransform, inCoords ), dot( inVTransform, inCoords ) );
+}
diff --git a/res/effectlib/funcsampleAreaGlossyDefault.glsllib b/res/effectlib/funcsampleAreaGlossyDefault.glsllib
new file mode 100644
index 0000000..cb9cba1
--- /dev/null
+++ b/res/effectlib/funcsampleAreaGlossyDefault.glsllib
@@ -0,0 +1,42 @@
+#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 )
+{
+ float sigmaU = clamp( 0.5 * roughU, 0.005, 0.5 );
+ float sigmaV = clamp( 0.5 * roughV, 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)) );
+
+ // 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 );
+
+ 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] += UVset[4]; UVset[1] += UVset[4];
+ UVset[2] += UVset[4]; UVset[3] += UVset[4];
+
+ vec2 UVmin = UVset[4], UVmax = UVset[4];
+ vec2 cminUV, cmaxUV;
+ UVmin = min(UVmin, UVset[0]); UVmax = max(UVmax, UVset[0]);
+ UVmin = min(UVmin, UVset[1]); UVmax = max(UVmax, UVset[1]);
+ 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) );
+
+ vec2 hitScale = (cmaxUV - cminUV);
+ vec2 fullScale = (UVmax - UVmin);
+ float intensity = ( hitScale.x * hitScale.y ) / max( fullScale.x * fullScale.y, 0.0001 );
+
+ return vec3( wt * intensity );
+}
diff --git a/res/effectlib/funcsampleLightVars.glsllib b/res/effectlib/funcsampleLightVars.glsllib
new file mode 100644
index 0000000..85ca144
--- /dev/null
+++ b/res/effectlib/funcsampleLightVars.glsllib
@@ -0,0 +1,29 @@
+#define MAX_NUM_LIGHTS 16
+
+struct LightSource
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+layout (std140) uniform cbBufferLights
+{
+ int uNumLights;
+ LightSource lights[MAX_NUM_LIGHTS];
+};
diff --git a/res/effectlib/funcspecularBSDF.glsllib b/res/effectlib/funcspecularBSDF.glsllib
new file mode 100644
index 0000000..e9450bf
--- /dev/null
+++ b/res/effectlib/funcspecularBSDF.glsllib
@@ -0,0 +1,42 @@
+#include "luminance.glsllib"
+
+#ifndef scatter_reflect
+#define scatter_reflect 0
+#define scatter_transmit 1
+#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 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;
+ }
+ }
+ 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 );
+}
diff --git a/res/effectlib/gles2/SSAOCustomMaterial.glsllib b/res/effectlib/gles2/SSAOCustomMaterial.glsllib
new file mode 100644
index 0000000..ea8d164
--- /dev/null
+++ b/res/effectlib/gles2/SSAOCustomMaterial.glsllib
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** 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 SSAO_CUSTOM_MATERIAL_GLSLLIB
+#define SSAO_CUSTOM_MATERIAL_GLSLLIB
+
+#ifndef QT3DS_ENABLE_SSAO
+#define QT3DS_ENABLE_SSAO 0
+#endif
+
+#ifndef QT3DS_ENABLE_SSDO
+#define QT3DS_ENABLE_SSDO 0
+#endif
+
+#if QT3DS_ENABLE_SSAO || QT3DS_ENABLE_SSDO
+
+#include "viewProperties.glsllib"
+#if QT3DS_ENABLE_SSDO
+#include "screenSpaceDO.glsllib"
+
+
+uniform vec4 ao_properties;
+uniform vec4 ao_properties2;
+uniform vec4 shadow_properties;
+uniform vec4 aoScreenConst;
+uniform vec4 UvToEyeConst;
+
+
+uniform sampler2D depth_sampler;
+#endif
+uniform sampler2D ao_sampler;
+uniform vec2 ao_sampler_size;
+
+#endif // QT3DS_ENABLE_SSAO || QT3DS_ENABLE_SSDO
+
+#if QT3DS_ENABLE_SSAO
+
+float customMaterialAO()
+{
+#if QT3DS_ENABLE_SSDO
+ vec2 smpUV = (gl_FragCoord.xy) * aoScreenConst.zw;
+#else
+ vec2 smpUV = gl_FragCoord.xy / ao_sampler_size;
+#endif
+ return texture(ao_sampler, smpUV).x;
+}
+
+#else
+
+float customMaterialAO()
+{
+ return 1.0;
+}
+
+#endif
+
+#if QT3DS_ENABLE_SSDO
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return shadowOcclusion( depth_sampler, lightDir, varWorldPos, view_matrix, view_projection_matrix, shadow_properties, camera_properties, aoScreenConst, UvToEyeConst );
+}
+
+#else
+
+float customMaterialShadow( vec3 lightDir, vec3 varWorldPos )
+{
+ return 1.0;
+}
+
+#endif
+
+#endif // #ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
diff --git a/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib b/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib
new file mode 100644
index 0000000..2f3bd15
--- /dev/null
+++ b/res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float calcRGBAvg(in vec4 rgba)
+{
+ return (rgba.r + rgba.g + rgba.b) / 3.0;
+}
+
+vec3 defaultMaterialBumpNoLod(in sampler2D sampler, in float factor,
+ in vec2 texCoord, in vec3 tangent, in vec3 binormal,
+ in vec3 normal, in vec2 bumpSize )
+{
+ // invert factor
+ float invFactor = -factor;
+
+ vec2 unitStep = 1.0 / bumpSize;
+
+ float du = calcRGBAvg(texture2D( sampler, vec2( texCoord.x + unitStep.x, texCoord.y )))
+ - calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y )));
+ float dv = calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y + unitStep.y )))
+ - calcRGBAvg(texture2D( sampler, vec2( texCoord.x, texCoord.y )));
+
+ vec3 n = normalize(vec3(invFactor * du, invFactor * dv, 1.0));
+ n = n.x * normalize(tangent) + n.y * normalize(binormal) + n.z * normal;
+ return normalize(normal + n);
+}
diff --git a/res/effectlib/gles2/evalEnvironmentMap.glsllib b/res/effectlib/gles2/evalEnvironmentMap.glsllib
new file mode 100644
index 0000000..ac9851e
--- /dev/null
+++ b/res/effectlib/gles2/evalEnvironmentMap.glsllib
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec3 evalEnvironmentMap( in vec3 R, float roughness )
+{
+ // convert R to spherical texture coordinates
+ vec2 tc = vec2( ( atan( R.x, -R.z ) + PI ) / ( PI_TWO ), acos( -R.y ) / PI );
+
+ return( textureLod( uEnvironmentTexture, tc, 0.0 ).rgb );
+}
diff --git a/res/effectlib/gles2/funcareaLightVars.glsllib b/res/effectlib/gles2/funcareaLightVars.glsllib
new file mode 100644
index 0000000..cdb8c92
--- /dev/null
+++ b/res/effectlib/gles2/funcareaLightVars.glsllib
@@ -0,0 +1,29 @@
+#define MAX_AREA_LIGHTS 16
+
+// note this struct must exactly match the memory layout of the
+// struct SLightSourceShader in the source code. If you make changes here you need
+// to adjust the struct SLightSourceShader as well
+struct AreaLight
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+uniform int uNumAreaLights;
+uniform AreaLight arealights[MAX_AREA_LIGHTS];
diff --git a/res/effectlib/gles2/funcsampleLightVars.glsllib b/res/effectlib/gles2/funcsampleLightVars.glsllib
new file mode 100644
index 0000000..6cb0d83
--- /dev/null
+++ b/res/effectlib/gles2/funcsampleLightVars.glsllib
@@ -0,0 +1,27 @@
+
+#define MAX_NUM_LIGHTS 16
+
+struct LightSource
+{
+ vec4 position;
+ vec4 direction; // Specifies the light direction in world coordinates.
+ vec4 up;
+ vec4 right;
+ vec4 diffuse;
+ vec4 ambient;
+ vec4 specular;
+ float spotExponent; // Specifies the intensity distribution of the light.
+ float spotCutoff; // Specifies the maximum spread angle of the light.
+ float constantAttenuation; // Specifies the constant light attenuation factor.
+ float linearAttenuation; // Specifies the linear light attenuation factor.
+ float quadraticAttenuation; // Specifies the quadratic light attenuation factor.
+ float range; // Specifies the maximum distance of the light influence
+ float width; // Specifies the width of the area light surface.
+ float height; // Specifies the height of the area light surface;
+ vec4 shadowControls;
+ mat4 shadowView;
+ int shadowIdx;
+};
+
+uniform int uNumLights;
+uniform LightSource lights[MAX_NUM_LIGHTS];
diff --git a/res/effectlib/gles2/microfacetBSDF.glsllib b/res/effectlib/gles2/microfacetBSDF.glsllib
new file mode 100644
index 0000000..7173a74
--- /dev/null
+++ b/res/effectlib/gles2/microfacetBSDF.glsllib
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** 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 MICROFACET_BSDF_GLSLLIB
+#define MICROFACET_BSDF_GLSLLIB 1
+
+
+float GtermSchlick( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = roughness*roughness*0.79788;
+
+ float G_V = NdotV / (NdotV * (1.0 + k) + k);
+ float G_L = NdotL / (NdotL * (1.0 + k) + k);
+
+ return clamp(( G_V * G_L ), 0.0, 1.0);
+}
+
+float GtermGGX( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = clamp(roughness*roughness, 0.00, 1.0);
+
+ float G_V = NdotV + sqrt( (NdotV - NdotV * k) * NdotV + k );
+ float G_L = NdotL + sqrt( (NdotL - NdotL * k) * NdotL + k );
+
+ return clamp( 2.0 / ( G_V * G_L ), 0.0, 1.0);
+}
+
+float DtermGGX( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughness )
+{
+ float m = clamp(roughness, 0.04, 1.0);
+ float m2 = m*m;
+
+ vec3 H = normalize(L + V);
+ float NdotH = clamp(dot( tanFrame[2], H ), 0.0001, 1.0);
+ float NdotH2 = NdotH * NdotH;
+
+ float denom = NdotH2 * (m2 - 1.0) + 1.0;
+ float D = m2 / (PI * denom * denom);
+
+ return max( 0.0, D);
+}
+
+float DtermGGXAniso( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughnessU, float roughnessV )
+{
+ float roughU = clamp(roughnessU, 0.04, 1.0);
+ float roughV = clamp(roughnessV, 0.04, 1.0);
+ vec3 H = normalize(L + V);
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float D = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ D = 1.0 / ( m * D * D );
+
+ return max( 0.0, D);
+}
+
+vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
+ vec3 H = normalize(L + V);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+ float NdotL = dot(tanFrame[2], L);
+
+ if ( NdotL > 0.0 )
+ {
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ // G term
+ //float G = GtermSchlick( tanFrame, L, V, roughness );
+ float G = GtermGGX( tanFrame, L, V, roughness );
+
+ //float D = DtermGGX( tanFrame, L, V, roughness );
+ float D = DtermGGXAniso( tanFrame, L, V, roughnessU, roughnessV );
+ rgba.rgb = G * D * NdotL * lightSpecular;
+ }
+
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+ }
+
+ return rgba;
+}
+
+vec4 microfacetBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU,
+ in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ if ( uEnvironmentMappingEnabled )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+ rgb = 0.01 * evalEnvironmentMap( R, roughness );
+ rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV,
+ scatter_reflect ).rgb;
+ }
+#endif
+ return( vec4( rgb, 1.0 ) );
+}
+
+vec3 ImportanceGGX( in mat3 tanFrame, vec2 Xi, float roughness , vec3 N )
+{
+ float a = roughness * roughness;
+ float Phi = 2.0 * PI * Xi.y;
+ float CosTheta = (1.0 - Xi.x);
+ float SinTheta = sqrt( 1.0 - CosTheta * CosTheta );
+
+ vec3 H;
+ H.x = SinTheta * cos( Phi );
+ H.y = SinTheta * sin( Phi );
+ H.z = CosTheta;
+
+ // Tangent to world space
+ return tanFrame[0] * H.x + tanFrame[1] * H.y + tanFrame[2] * H.z;
+}
+
+float DtermGGXAnisoSampled( in mat3 tanFrame, in vec3 H, in float roughnessU, float roughnessV )
+{
+#if (MATERIAL_IS_NON_DIELECTRIC == 1)
+ float roughU = clamp(roughnessU*roughnessU, 0.01, 1.0);
+ float roughV = clamp(roughnessV*roughnessV, 0.01, 1.0);
+#else
+ float roughU = clamp(roughnessU, 0.02, 1.0);
+ float roughV = clamp(roughnessV, 0.02, 1.0);
+#endif
+
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float pdf = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ float D = 1.0 / ( m * pdf * pdf );
+
+ return max( 0.0, D);
+}
+
+vec3 sampleEnv(in vec3 L, float pdf, int sampleCount, float roughness )
+{
+ // convert coord to 2D
+ vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0 * PI ), acos( -L.y ) / PI );
+ return( textureLod( uEnvironmentTexture, tc, 0.0 ).rgb );
+}
+
+vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU,
+ in float roughnessV, int mode )
+{
+ vec2 hammersly[4];
+ hammersly[0] = vec2(0.0, 0.0);
+ hammersly[1] = vec2(0.25, 0.5);
+ hammersly[2] = vec2(0.5, 0.25);
+ hammersly[3] = vec2(0.75, 0.75);
+
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+
+ float roughness = clamp( calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ),
+ 0.0, 1.0 );
+
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+
+ const int NumSamples = 4;
+ for( int i = 0; i < NumSamples; i++ )
+ {
+ vec2 Xi = hammersly[i]; // pre computed values
+ //vec2 Xi = hammersley2d(i, NumSamples);
+ vec3 Half = ImportanceGGX( tanFrame, Xi, roughness , tanFrame[2] );
+ vec3 H = normalize( Half );
+
+ vec3 L = 2.0 * dot( viewDir, Half ) * Half - viewDir;
+ float NdotV = clamp( dot( tanFrame[2], viewDir ), 0.0001, 1.0 );
+ float NdotR = clamp( dot( tanFrame[2], R ), 0.0, 1.0 );
+ float NdotH = clamp( dot( tanFrame[2], H ), 0.0001, 1.0 );
+
+ if( NdotV > 0.0001 )
+ {
+ float G = GtermGGX( tanFrame, L, viewDir, roughness );
+ float D = DtermGGXAnisoSampled( tanFrame, H, roughnessU, roughnessV);
+
+ vec3 envColor = 0.01 * sampleEnv( L, D, NumSamples, roughness );
+
+ rgb += (envColor * G * D * NdotR) / ( 4.0 * NdotV * NdotH);
+ }
+ }
+
+ rgb /= float(NumSamples);
+
+ return( vec4( rgb, 1.0 ) );
+}
+
+#endif
diff --git a/res/effectlib/gles2/monoChannel.glsllib b/res/effectlib/gles2/monoChannel.glsllib
new file mode 100644
index 0000000..ca682d6
--- /dev/null
+++ b/res/effectlib/gles2/monoChannel.glsllib
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 MONO_CHANNEL_GLSLLIB
+#define MONO_CHANNEL_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#endif
+
+float monoChannel( in vec4 t, const in int monoSource )
+{
+ if ( monoSource == mono_alpha )
+ return( t.w );
+
+ if ( monoSource == mono_average )
+ return( ( t.x + t.y + t.z ) / 3.0 );
+
+ if ( monoSource == mono_luminance )
+ return( luminance( t.xyz ) );
+
+ if ( monoSource == mono_maximum )
+ return( max( t.x, max( t.y, t.z ) ) );
+
+ return( 1.0 );
+}
+
+#endif
diff --git a/res/effectlib/gles2/refraction.glsllib b/res/effectlib/gles2/refraction.glsllib
new file mode 100644
index 0000000..837d7f5
--- /dev/null
+++ b/res/effectlib/gles2/refraction.glsllib
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// this is entirly phiysical incorrect
+// We just use this to fake distortion when we have no environment available
+// The displacement is calculated on ior
+vec3 refraction( in sampler2D sampler, in float materialIOR )
+{
+ vec3 displace = fresnel( viewDir, vec3( materialIOR ));
+
+ float xdir = abs( viewDir.x );
+ float ydir = abs( viewDir.y );
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ vec2 newUV = vec2(gl_FragCoord.xy/texSize);
+ if ( xdir > ydir)
+ {
+ newUV = ( viewDir.x > 0.0) ? newUV + displace.xy : newUV - displace.xy;
+ }
+ else
+ {
+ newUV = ( viewDir.y > 0.0) ? newUV - displace.xy : newUV + displace.xy;
+ }
+
+ vec3 refractColor = texture( sampler, newUV ).rgb;
+
+ return refractColor;
+}
+
+// This should really not be used, but it's there for the sake of testing.
+vec3 refractBlur( in sampler2D sampler, in vec3 viewDir, in float materialIOR, in float blurWidth )
+{
+ // This is really terrible, but at least is a little better than
+ vec3 displace = viewDir * materialIOR;
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ vec2 newUV = vec2(gl_FragCoord.xy * texSize);
+ newUV += displace.xy * 0.005;
+
+ //vec3 refractColor = texture( sampler, newUV ).rgb;
+ vec3 refractColor = vec3(0);
+ int sz = int(ceil(blurWidth));
+ float wtsum = 0.0;
+
+ for (int y = -sz; y <= sz; ++y)
+ {
+ for (int x = -sz; x <= sz; ++x)
+ {
+ float wt = float(x*x + y*y) / (blurWidth * 0.5);
+ wt = exp2(-wt);
+ //refractColor += wt * textureOffset( sampler, newUV, ivec2(x, y) ).rgb;
+ vec2 uvOfs = vec2(x, y) * texSize;
+ refractColor += wt * texture( sampler, newUV+uvOfs).rgb;
+ wtsum += wt;
+ }
+ }
+
+ return refractColor / wtsum;
+}
diff --git a/res/effectlib/gles2/sampleProbe.glsllib b/res/effectlib/gles2/sampleProbe.glsllib
new file mode 100644
index 0000000..f785918
--- /dev/null
+++ b/res/effectlib/gles2/sampleProbe.glsllib
@@ -0,0 +1,482 @@
+/****************************************************************************
+**
+** 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/shadowMapping.glsllib b/res/effectlib/gles2/shadowMapping.glsllib
new file mode 100644
index 0000000..183ef97
--- /dev/null
+++ b/res/effectlib/gles2/shadowMapping.glsllib
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 SHADOW_MAPPING_GLSLLIB
+#define SHADOW_MAPPING_GLSLLIB
+
+#include "depthpass.glsllib"
+
+float sampleParaboloid( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps, out vec2 smpUV )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float ptDepth = depthValueToLinearDistance( 1.0 - smpCoord.z, cameraProps );
+ ptDepth = (ptDepth - cameraProps.x) / (cameraProps.y - cameraProps.x);
+ smpCoord = normalize( smpCoord.xyz );
+ smpCoord.xy /= -( smpCoord.z + 1.0 );
+ smpCoord.xy = vec2(1.0) - smpCoord.xy;
+ smpCoord.xy *= 0.5;
+
+ smpUV = smpCoord.xy; // This is just for debug purposes to ensure what the sampled UV cooord is.
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+ sampleDepth *= sampleDepth;
+ ptDepth *= ptDepth;
+ float shadowFac = min(1.0, exp(shadowControls.y * sampleDepth * sampleDepth) / exp(shadowControls.y * ptDepth * ptDepth));
+
+ smpUV.xy *= shadowFac;
+ return shadowFac;
+}
+
+float sampleCubemap( in samplerCube shadowCube, in vec4 shadowControls, in mat4 shadowViewMat, in vec3 lightPos, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec3 viewDir = worldPos - vec3(lightPos.x, lightPos.y, lightPos.z);
+ float ptDepth = length(viewDir.xyz);
+ vec4 viewCoord = shadowViewMat * vec4( viewDir.xyz, 0.0 );
+ viewCoord.xyz /= ptDepth;
+ ptDepth = clamp((ptDepth - 1.0) / (cameraProps.y - 1.0), 0.0, 1.0);
+
+ float smpDepth = textureCube( shadowCube, viewDir.xyz ).x + shadowControls.x;
+
+ float shadowFac = min(1.0, exp(shadowControls.y * smpDepth) / exp(shadowControls.y * ptDepth));
+ return shadowFac;
+}
+
+float sampleOrthographic( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+
+ return min(1.0, exp(shadowControls.y * sampleDepth) / exp(shadowControls.y * smpCoord.z));
+}
+
+
+struct ParaboloidMapResult
+{
+ vec4 m_Position;
+ vec4 m_WorldPos;
+};
+
+ParaboloidMapResult VertexParaboloidDepth(vec3 pos, mat4 inMVP)
+{
+ vec4 glPos = inMVP * vec4( pos, 1.0 );
+ glPos /= glPos.w;
+ glPos.xyz = normalize( glPos.xyz );
+ vec4 world_pos;
+ world_pos.w = glPos.z;
+ glPos.xy /= glPos.z + 1.0;
+ world_pos.xyz = pos.xyz;
+
+ ParaboloidMapResult retval;
+ retval.m_Position = glPos;
+ retval.m_WorldPos = world_pos;
+ return retval;
+}
+
+#endif
diff --git a/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib b/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib
new file mode 100644
index 0000000..daae401
--- /dev/null
+++ b/res/effectlib/gles2/tangentSpaceNormalTexture.glsllib
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 FILE_NORMAL_TEXTURE_GLSLLIB
+#define FILE_NORMAL_TEXTURE_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+int modulo(int a, int b)
+{
+ int k = (a / b);
+ return a - k*b;
+}
+
+//interpreting the color values of a bitmap as a vector in tangent space
+vec3 tangentSpaceNormalTexture( in sampler2D tex, in float factor, in bool flipTangentU, in bool flipTangentV
+ , in texture_coordinate_info uvw, in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV )
+{
+ // if we mirror repeat a tangent space texture, tangent space needs to be flipped for every other tile
+ bool flipU = flipTangentU;
+ bool flipV = flipTangentV;
+ if ( wrapU == wrap_mirrored_repeat )
+ {
+ if ( ( ( 0.0 < uvw.position.x ) && ( modulo(int( uvw.position.x ), 2) == 1 ) )
+ || ( ( uvw.position.x < 0.0 ) && ( modulo(int( uvw.position.x ), 2) == 0 ) ) )
+ {
+ flipU = !flipU;
+ }
+ if ( ( ( 0.0 < uvw.position.y ) && ( modulo(int( uvw.position.y ), 2) == 1 ) )
+ || ( ( uvw.position.y < 0.0 ) && ( modulo(int( uvw.position.y ), 2) == 0 ) ) )
+ {
+ flipV = !flipV;
+ }
+ }
+
+ vec3 tangent = 2.0 * texture( tex, uvw.position.xy ).xyz - 1.0;
+
+ vec3 tangentU = normalize( flipU ? -uvw.tangent_u : uvw.tangent_u );
+ vec3 tangentV = normalize( flipV ? -uvw.tangent_v : uvw.tangent_v );
+ vec3 normal = normalize( cross( tangentU, tangentV ) );
+
+ return( mix( normal, normalize( tangent.x * tangentU - tangent.y * tangentV + tangent.z * normal ), factor ) );
+}
+
+#include "textureCoordinateInfo.glsllib"
+
+//Simpler version built to run from UIC image data
+//In our case, we have already generated the texture coordinate x,y position
+//TODO - figure out if we need to manipulate tangent_u, tangent_v.
+vec3 defaultMaterialFileNormalTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal )
+{
+ // factor should be in [0,1] range
+ return tangentSpaceNormalTexture( sampler, clamp(factor, 0.0, 1.0), false, false
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal )
+ , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+ , wrap_repeat, wrap_repeat);
+}
+
+#endif
diff --git a/res/effectlib/gradient3Recolor.glsllib b/res/effectlib/gradient3Recolor.glsllib
new file mode 100644
index 0000000..ba7d593
--- /dev/null
+++ b/res/effectlib/gradient3Recolor.glsllib
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float gradientInterpolate( in int interpolationMode, in float value )
+{
+ switch( interpolationMode )
+ {
+ case gradient_interpolation_linear :
+ return( value );
+ case gradient_interpolation_off :
+ return( 0.0 );
+ case gradient_interpolation_ease_in :
+ return( 1.0 - pow( 1.0 - value, 2.0/3.0 ) );
+ case gradient_interpolation_ease_out :
+ return( pow( value, 2.0/3.0 ) );
+ case gradient_interpolation_ease_in_out :
+ return( ( value <= 0.5 )
+ ? 0.5 * pow( 2.0 * value, 2.0/3.0 )
+ : 0.5 + 0.5 * ( 1.0 - pow( 2.0 * ( 1.0 - value ), 2.0/3.0 ) ) );
+ default:
+ return( value ); // default is linear
+ }
+}
+
+texture_return gradient3Recolor( in float gradientPositions[3], in vec3 gradientColors[3], in int interpolationModes[3], in int monoSource, in float distortion, in float position )
+{
+ texture_return tr;
+ float pos = position + distortion;
+ if ( pos <= gradientPositions[0] )
+ {
+ tr.tint = gradientColors[0];
+ }
+ else if ( pos >= gradientPositions[2] )
+ {
+ tr.tint = gradientColors[2];
+ }
+ else
+ {
+ int index = ( position < gradientPositions[1] ) ? 0 : 1;
+ float relPos = gradientInterpolate( interpolationModes[index], ( pos - gradientPositions[index] ) / ( gradientPositions[index+1] - gradientPositions[index] ) );
+ tr.tint = mix( gradientColors[index], gradientColors[index+1], relPos );
+ }
+ tr.mono = 0.0;
+ return( tr );
+}
+
diff --git a/res/effectlib/gradient3Texture.glsllib b/res/effectlib/gradient3Texture.glsllib
new file mode 100644
index 0000000..7bd6cec
--- /dev/null
+++ b/res/effectlib/gradient3Texture.glsllib
@@ -0,0 +1,36 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+texture_return gradient3Texture( in int gradientMode, in float gradientPositions[3], in vec3 gradientColors[3], in int interpolationModes[3], in texture_coordinate_info uvw, in float distortion )
+{
+ float position = gradientGetPosition( gradientMode, uvw.position.xy );
+ return( gradient3Recolor( gradientPositions, gradientColors, interpolationModes, 0, distortion, position ) );
+}
+
diff --git a/res/effectlib/gradientGetPosition.glsllib b/res/effectlib/gradientGetPosition.glsllib
new file mode 100644
index 0000000..4ceece0
--- /dev/null
+++ b/res/effectlib/gradientGetPosition.glsllib
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+
+// calculate the length of the hypotenuse of a right-angle triangle
+float hypot( in float x, in float y )
+{
+ // (sqrt( x * x + y * y )) might over- or underflow
+ // see http://en.wikipedia.org/wiki/Hypot for details
+ x = abs( x );
+ y = abs( y );
+ float t = min( x, y );
+ x = max( x, y );
+ t = t/x;
+ return( x * sqrt( 1.0 + ( t * t ) ) );
+}
+
+float gradientGetPosition( in int gradientMode, in vec2 xy )
+{
+ // clamp to [0,1]
+ vec2 tex = xy - floor( xy );
+
+ switch( gradientMode )
+ {
+ case gradient_linear :
+ return( tex.x );
+ case gradient_squared :
+ return( tex.x * tex.x );
+ case gradient_box :
+ // gradient is based on the distance from the center
+ return( max( abs( tex.x - 0.5 ), abs( tex.y - 0.5 ) ) );
+ case gradient_diagonal :
+ // gradient is based on the distance from the diagonal
+ return( sqrt(2.0) * abs( tex.x - tex.y ) );
+ case gradient_90_degree :
+ // Need to check
+ return( 0.0 );
+ case gradient_symmetric_90_degree :
+ // Need to check
+ return( 0.0 );
+ case gradient_radial :
+ // Distance from center
+ return( 2.0 * hypot( tex.x - 0.5, tex.y - 0.5 ) );
+ case gradient_360_degree :
+ // fall through need to check
+ default :
+ return( 0.0 );
+ }
+}
diff --git a/res/effectlib/luminance.glsllib b/res/effectlib/luminance.glsllib
new file mode 100644
index 0000000..067dc18
--- /dev/null
+++ b/res/effectlib/luminance.glsllib
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 LUMINANCE_GLSLLIB
+#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 );
+
+float luminance( in vec3 v )
+{
+ 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
diff --git a/res/effectlib/miNoise.glsllib b/res/effectlib/miNoise.glsllib
new file mode 100644
index 0000000..5fbff37
--- /dev/null
+++ b/res/effectlib/miNoise.glsllib
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 miNoise( in vec3 xyz )
+{
+ const float div = 1.0 / 256.0;
+
+ ivec3 itmp = ivec3( xyz );
+ ivec3 ixyz[3] = ivec3[]( itmp & 0xFF, itmp+1 & 0xFF, itmp+2 & 0xFF );
+ vec3 fxyz = xyz - floor( xyz );
+
+ vec3 dux, ux;
+ dux.z = fxyz.x * div;
+ dux.y = div - 2.0 * dux.z;
+ dux.x = dux.z - div;
+ ux.z = 0.5 * fxyz.x * dux.z;
+ ux.y = dux.z + 0.5 * ( div - fxyz.x * dux.z );
+ ux.x = ux.z - dux.z + 0.5 * div;
+
+ vec3 duy, uy;
+ duy.z = fxyz.y;
+ duy.y = 1.0 - 2.0 * duy.z;
+ duy.x = duy.z - 1.0;
+ uy.z = 0.5 * square( duy.z );
+ uy.y = duy.z + 0.5 - square( duy.z );
+ uy.x = uy.z - duy.z + 0.5;
+
+ float duz[3] = float[]( fxyz.z - 1.0, 1.0 - 2.0 * fxyz.z, fxyz.z );
+ float uz[3] = float[]( 0.5 * square( fxyz.z ) - fxyz.z + 0.5, fxyz.z + 0.5 - square( fxyz.z ), 0.5 * square( fxyz.z ) );
+
+ int xx = random255X( ixyz[0].x );
+ int yx = random255Y( ixyz[0].y );
+ int zx = random255Z( ixyz[0].z );
+ int xy = random255X( ixyz[1].x );
+ int yy = random255Y( ixyz[1].y );
+ int zy = random255Z( ixyz[1].z );
+
+ int xxxy = xx ^ xy;
+ int yxxy = yx ^ xy;
+ int zxxy = zx ^ xy;
+ int xxyy = xx ^ yy;
+ int yxyy = yx ^ yy;
+ int zxyy = zx ^ yy;
+ int xxzy = xx ^ zy;
+ int yxzy = yx ^ zy;
+ int zxzy = zx ^ zy;
+
+ int ixyzxx = ixyz[0].x ^ ixyz[1].x;
+ int ixyzyx = ixyz[0].y ^ ixyz[1].x;
+ int ixyzzx = ixyz[0].z ^ ixyz[1].x;
+ int ixyzxy = ixyz[0].x ^ ixyz[1].y;
+ int ixyzyy = ixyz[0].y ^ ixyz[1].y;
+ int ixyzzy = ixyz[0].z ^ ixyz[1].y;
+ int ixyzxz = ixyz[0].x ^ ixyz[1].z;
+ int ixyzyz = ixyz[0].y ^ ixyz[1].z;
+ int ixyzzz = ixyz[0].z ^ ixyz[1].z;
+
+
+ vec4 ret = vec4( 0.0, 0.0, 0.0, 0.0 );
+
+ for ( int i=0 ; i<3 ; i++ )
+ {
+ int iz = random255Z( ixyz[2][i] );
+
+ mat3x3 nf = mat3x3( vec3( float( random255W( xxxy ^ iz ^ random255W( ixyzxx ^ ixyz[2][i] ) ) )
+ , float( random255W( yxxy ^ iz ^ random255W( ixyzyx ^ ixyz[2][i] ) ) )
+ , float( random255W( zxxy ^ iz ^ random255W( ixyzzx ^ ixyz[2][i] ) ) ) )
+ , vec3( float( random255W( xxyy ^ iz ^ random255W( ixyzxy ^ ixyz[2][i] ) ) )
+ , float( random255W( yxyy ^ iz ^ random255W( ixyzyy ^ ixyz[2][i] ) ) )
+ , float( random255W( zxyy ^ iz ^ random255W( ixyzzy ^ ixyz[2][i] ) ) ) )
+ , vec3( float( random255W( xxzy ^ iz ^ random255W( ixyzxz ^ ixyz[2][i] ) ) )
+ , float( random255W( yxzy ^ iz ^ random255W( ixyzyz ^ ixyz[2][i] ) ) )
+ , float( random255W( zxzy ^ iz ^ random255W( ixyzzz ^ ixyz[2][i] ) ) ) ) );
+
+ float fxdz = dot( uy, dux * nf );
+ vec3 dy = ux * nf;
+ float dz = dot( uy, dy );
+
+ ret.x += uz[i] * fxdz;
+ ret.y += uz[i] * dot( duy, dy );
+ ret.z += duz[i] * dz;
+ ret.w += uz[i] * dz;
+ }
+ return( ret );
+}
+
diff --git a/res/effectlib/microfacetBSDF.glsllib b/res/effectlib/microfacetBSDF.glsllib
new file mode 100644
index 0000000..8e48910
--- /dev/null
+++ b/res/effectlib/microfacetBSDF.glsllib
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** 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 MICROFACET_BSDF_GLSLLIB
+#define MICROFACET_BSDF_GLSLLIB 1
+
+
+float GtermSchlick( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = roughness*roughness*0.79788;
+
+ float G_V = NdotV / (NdotV * (1.0 + k) + k);
+ float G_L = NdotL / (NdotL * (1.0 + k) + k);
+
+ return clamp(( G_V * G_L ), 0.0, 1.0);
+}
+
+float GtermGGX( in mat3 tanFrame, in vec3 l, in vec3 v, in float roughness )
+{
+ float NdotV = clamp(dot(tanFrame[2], v), 0.0, 1.0);
+ float NdotL = clamp(dot(tanFrame[2], l), 0.0, 1.0);
+ float k = clamp(roughness*roughness, 0.00, 1.0);
+
+ float G_V = NdotV + sqrt( (NdotV - NdotV * k) * NdotV + k );
+ float G_L = NdotL + sqrt( (NdotL - NdotL * k) * NdotL + k );
+
+ return clamp( 2.0 / ( G_V * G_L ), 0.0, 1.0);
+}
+
+float DtermGGX( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughness )
+{
+ float m = clamp(roughness, 0.04, 1.0);
+ float m2 = m*m;
+
+ vec3 H = normalize(L + V);
+ float NdotH = clamp(dot( tanFrame[2], H ), 0.0001, 1.0);
+ float NdotH2 = NdotH * NdotH;
+
+ float denom = NdotH2 * (m2 - 1.0) + 1.0;
+ float D = m2 / (PI * denom * denom);
+
+ return max( 0.0, D);
+}
+
+float DtermGGXAniso( in mat3 tanFrame, in vec3 L, in vec3 V, in float roughnessU, float roughnessV )
+{
+ float roughU = clamp(roughnessU, 0.04, 1.0);
+ float roughV = clamp(roughnessV, 0.04, 1.0);
+ vec3 H = normalize(L + V);
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float D = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ D = 1.0 / ( m * D * D );
+
+ return max( 0.0, D);
+}
+
+vec4 microfacetBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
+ vec3 H = normalize(L + V);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+ float NdotL = dot(tanFrame[2], L);
+
+ if ( NdotL > 0.0 )
+ {
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ // G term
+ //float G = GtermSchlick( tanFrame, L, V, roughness );
+ float G = GtermGGX( tanFrame, L, V, roughness );
+
+ //float D = DtermGGX( tanFrame, L, V, roughness );
+ float D = DtermGGXAniso( tanFrame, L, V, roughnessU, roughnessV );
+ rgba.rgb = G * D * NdotL * lightSpecular;
+ }
+
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+ }
+
+ return rgba;
+}
+
+vec4 microfacetBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ if ( uEnvironmentMappingEnabled )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+ rgb = 0.01 * evalEnvironmentMap( R, roughness );
+ rgb = microfacetBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb;
+ }
+#endif
+ return( vec4( rgb, 1.0 ) );
+}
+
+
+// see http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+
+float radicalInverse_VdC( uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+ }
+
+vec2 hammersley2d(uint i, uint N)
+{
+ return vec2(float(i)/float(N), radicalInverse_VdC(i));
+}
+
+vec2 hammersly[4] = vec2[4] (
+ vec2(0.0, 0.0),
+ vec2(0.25, 0.5),
+ vec2(0.5, 0.25),
+ vec2(0.75, 0.75)
+ );
+
+vec3 ImportanceGGX( in mat3 tanFrame, vec2 Xi, float roughness , vec3 N )
+{
+ float a = roughness * roughness;
+ float Phi = 2.0 * PI * Xi.y;
+ float CosTheta = (1.0 - Xi.x);
+ float SinTheta = sqrt( 1.0 - CosTheta * CosTheta );
+
+ vec3 H;
+ H.x = SinTheta * cos( Phi );
+ H.y = SinTheta * sin( Phi );
+ H.z = CosTheta;
+
+ // Tangent to world space
+ return tanFrame[0] * H.x + tanFrame[1] * H.y + tanFrame[2] * H.z;
+}
+
+float DtermGGXAnisoSampled( in mat3 tanFrame, in vec3 H, in float roughnessU, float roughnessV )
+{
+#if (MATERIAL_IS_NON_DIELECTRIC == 1)
+ float roughU = clamp(roughnessU*roughnessU, 0.01, 1.0);
+ float roughV = clamp(roughnessV*roughnessV, 0.01, 1.0);
+#else
+ float roughU = clamp(roughnessU, 0.02, 1.0);
+ float roughV = clamp(roughnessV, 0.02, 1.0);
+#endif
+
+ float NdotH = clamp( dot(tanFrame[2], H), 0.0001, 1.0 );
+ float m = PI * roughU * roughV;
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float x2 = roughU*roughU;
+ float y2 = roughV*roughV;
+
+ float pdf = (HdotX*HdotX/x2) + (HdotY*HdotY/y2) + (NdotH*NdotH);
+ float D = 1.0 / ( m * pdf * pdf );
+
+ return max( 0.0, D);
+}
+
+vec3 sampleEnv(in vec3 L, float pdf, uint sampleCount, float roughness )
+{
+ vec2 envMapSize = vec2( textureSize( uEnvironmentTexture, 0 ) );
+ float envMapLevels = log2( max( envMapSize.x, envMapSize.y ) );
+
+ float a = 0.5*log2( float(envMapSize.x*envMapSize.y) / float(sampleCount) );
+ float d = 4.0 * (abs(L.z) + 1.0) * (abs(L.z) + 1.0);
+ float b = 0.5*log2( pdf * d );
+
+ // convert coord to 2D
+ vec2 tc = vec2( ( atan( L.x, -L.z ) + PI ) / ( 2.0 * PI ), acos( -L.y ) / PI );
+ float weight = step( 0.0001, roughness );
+
+ float lod = max( 0.0, min( (a - b)*weight, envMapLevels ));
+
+ return( textureLod( uEnvironmentTexture, tc, lod ).rgb );
+}
+
+vec4 microfacetSampledBSDF( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+
+ float roughness = clamp( calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] ), 0.0, 1.0 );
+
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+
+ const uint NumSamples = 4u;
+ for( uint i = 0u; i < NumSamples; i++ )
+ {
+ vec2 Xi = hammersly[i]; // pre computed values
+ //vec2 Xi = hammersley2d(i, NumSamples);
+ vec3 Half = ImportanceGGX( tanFrame, Xi, roughness , tanFrame[2] );
+ vec3 H = normalize( Half );
+
+ vec3 L = 2.0 * dot( viewDir, Half ) * Half - viewDir;
+ float NdotV = clamp( dot( tanFrame[2], viewDir ), 0.0001, 1.0 );
+ float NdotR = clamp( dot( tanFrame[2], R ), 0.0, 1.0 );
+ float NdotH = clamp( dot( tanFrame[2], H ), 0.0001, 1.0 );
+
+ if( NdotV > 0.0001 )
+ {
+ float G = GtermGGX( tanFrame, L, viewDir, roughness );
+ float D = DtermGGXAnisoSampled( tanFrame, H, roughnessU, roughnessV);
+
+ vec3 envColor = 0.01 * sampleEnv( L, D, NumSamples, roughness );
+
+ rgb += (envColor * G * D * NdotR) / ( 4.0 * NdotV * NdotH);
+ }
+ }
+
+ rgb /= float(NumSamples);
+
+ return( vec4( rgb, 1.0 ) );
+}
+
+#endif
diff --git a/res/effectlib/monoChannel.glsllib b/res/effectlib/monoChannel.glsllib
new file mode 100644
index 0000000..5c03a97
--- /dev/null
+++ b/res/effectlib/monoChannel.glsllib
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 MONO_CHANNEL_GLSLLIB
+#define MONO_CHANNEL_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+#define mono_alpha 0
+#define mono_average 1
+#define mono_luminance 2
+#define mono_maximum 3
+#endif
+
+float monoChannel( in vec4 t, in int monoSource )
+{
+ switch( monoSource )
+ {
+ case mono_alpha :
+ return( t.w );
+ case mono_average :
+ return( ( t.x + t.y + t.z ) / 3.0 );
+ case mono_luminance :
+ return( luminance( t.xyz ) );
+ case mono_maximum :
+ return( max( t.x, max( t.y, t.z ) ) );
+ default :
+ return( 1.0 );
+ }
+}
+
+#endif
diff --git a/res/effectlib/normalizedMix.glsllib b/res/effectlib/normalizedMix.glsllib
new file mode 100644
index 0000000..fc90b46
--- /dev/null
+++ b/res/effectlib/normalizedMix.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 normalizedMix( in bsdf_component components[1] )
+{
+ return( components[0].component );
+}
+
+vec4 normalizedMix( in bsdf_component components[2] )
+{
+ float sum = components[0].weight + components[1].weight;
+ float invSum = ( sum <= 1.0 ) ? 1.0 : 1.0 / sum;
+ return( invSum * ( components[0].weight * components[0].component + components[1].weight * components[1].component ) );
+}
+
diff --git a/res/effectlib/perlinNoise.glsllib b/res/effectlib/perlinNoise.glsllib
new file mode 100644
index 0000000..347386c
--- /dev/null
+++ b/res/effectlib/perlinNoise.glsllib
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// check out implementation from GPU Gems 1 and 2
+
+float fade( in float x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+vec2 fade( in vec2 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+vec3 fade( in vec3 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+vec4 fade( in vec4 x )
+{
+ return( x * x * x * ( x * ( x * 6.0 - 15.0 ) + 10.0 ));
+ //return( x * x * ( 3.0 - 2.0 * x ) );
+}
+
+float influence( in int hash, in float x )
+{
+ return( x * texelFetch( randomGradient1D, ivec2(hash, 0), 0 ).x );
+}
+
+float influence( in int hash, in float x, in float y )
+{
+ return( dot( vec2( x, y ), texelFetch( randomGradient2D, ivec2(hash, 0), 0 ).xy ) );
+}
+
+float influence( in int hash, in float x, in float y, in float z )
+{
+ return( dot( vec3( x, y, z ), texelFetch( randomGradient3D, ivec2(hash, 0), 0 ).xyz ) );
+}
+
+float influence( in int hash, in float x, in float y, in float z, in float w )
+{
+ return( dot( vec4( x, y, z, w ), texelFetch( randomGradient4D, ivec2(hash, 0), 0 ) ) );
+}
+
+float perlinNoise( in float pos )
+{
+ float floorPos = floor( pos );
+ int intPos = int( floorPos );
+ float fracPos = pos - floorPos;
+
+ return( mix( influence( random255X( intPos ), fracPos ), influence( random255X( intPos+1 ), fracPos - 1.0 ), fade( fracPos ) ) );
+}
+
+float perlinNoise( in vec2 pos )
+{
+ vec2 floorPos = floor( pos );
+ vec2 fracPos = pos - floorPos;
+ vec2 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+
+ return( mix( mix( influence( ax^ay, fracPos.x, fracPos.y )
+ , influence( bx^ay, fracPos.x - 1.0, fracPos.y ), fadedPos.x )
+ , mix( influence( ax^by, fracPos.x, fracPos.y - 1.0 )
+ , influence( bx^by, fracPos.x - 1.0, fracPos.y - 1.0 ), fadedPos.x ), fadedPos.y ) );
+}
+
+float perlinNoise( in vec3 pos )
+{
+ vec3 floorPos = floor( pos );
+ vec3 fracPos = pos - floorPos;
+ vec3 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+ int az = random255Z( int(floorPos.z) );
+ int bz = random255Z( int(floorPos.z) + 1 );
+
+ int axay = ax ^ ay;
+ int bxay = bx ^ ay;
+ int axby = ax ^ by;
+ int bxby = bx ^ by;
+
+ return( mix( mix( mix( influence( axay^az, fracPos.x, fracPos.y, fracPos.z )
+ , influence( bxay^az, fracPos.x - 1.0, fracPos.y, fracPos.z ), fadedPos.x )
+ , mix( influence( axby^az, fracPos.x, fracPos.y - 1.0, fracPos.z )
+ , influence( bxby^az, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bz, fracPos.x, fracPos.y , fracPos.z - 1.0 )
+ , influence( bxay^bz, fracPos.x - 1.0, fracPos.y , fracPos.z - 1.0 ), fadedPos.x )
+ , mix( influence( axby^bz, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0 )
+ , influence( bxby^bz, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0 ), fadedPos.x ), fadedPos.y ), fadedPos.z ) );
+}
+
+float perlinNoise( in vec4 pos )
+{
+ vec4 floorPos = floor( pos );
+ vec4 fracPos = pos - floorPos;
+ vec4 fadedPos = fade( fracPos );
+
+ int ax = random255X( int(floorPos.x) );
+ int bx = random255X( int(floorPos.x) + 1 );
+ int ay = random255Y( int(floorPos.y) );
+ int by = random255Y( int(floorPos.y) + 1 );
+ int az = random255Z( int(floorPos.z) );
+ int bz = random255Z( int(floorPos.z) + 1 );
+ int aw = random255W( int(floorPos.w) );
+
+ int axay = ax ^ ay;
+ int bxay = bx ^ ay;
+ int axby = ax ^ by;
+ int bxby = bx ^ by;
+
+ float result[2];
+ for ( int i=0 ; i<2 ; i++ )
+ {
+ int azaw = az ^ aw;
+ int bzaw = bz ^ aw;
+
+ result[i] = mix( mix( mix( influence( axay^azaw, fracPos.x, fracPos.y, fracPos.z, fracPos.w )
+ , influence( bxay^azaw, fracPos.x - 1.0, fracPos.y, fracPos.z, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^azaw, fracPos.x, fracPos.y - 1.0, fracPos.z, fracPos.w )
+ , influence( bxby^azaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z, fracPos.w ), fadedPos.x ), fadedPos.y )
+ , mix( mix( influence( axay^bzaw, fracPos.x, fracPos.y, fracPos.z - 1.0, fracPos.w )
+ , influence( bxay^bzaw, fracPos.x - 1.0, fracPos.y, fracPos.z - 1.0, fracPos.w ), fadedPos.x )
+ , mix( influence( axby^bzaw, fracPos.x, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w )
+ , influence( bxby^bzaw, fracPos.x - 1.0, fracPos.y - 1.0, fracPos.z - 1.0, fracPos.w ), fadedPos.x ), fadedPos.y ), fadedPos.z );
+ aw = random255W( int(floorPos.w) + 1 );
+ fracPos.w -= 1.0;
+ }
+ return( mix( result[0], result[1], fadedPos.w ) );
+}
+
+float summedPerlinNoise( in vec3 pos, in int terms, in bool absNoise )
+{
+ float sum = 0.0;
+ float weight = 1.0;
+ vec3 p = pos;
+ while ( terms-- != 0 )
+ {
+ float noise = perlinNoise( p );
+ sum += weight * ( absNoise ? abs(noise) : noise );
+ p += p;
+ weight *= 0.5;
+ }
+ return( sum );
+}
+
+float summedPerlinNoise( in vec4 pos, in int terms, in bool absNoise )
+{
+ float sum = 0.0;
+ float weight = 1.0;
+ vec4 p = pos;
+ while ( terms-- != 0 )
+ {
+ float noise = perlinNoise( p );
+ sum += weight * ( absNoise ? abs(noise) : noise );
+ p += p;
+ weight *= 0.5;
+ }
+ return( sum );
+}
+
+float perlinNoise( in vec3 pos, in float time, in int terms, in vec3 turbulenceWeight, in bool absoluteNoise, in bool applyMarble
+ , in bool applyDent, in float noiseBands, in float noiseThresholdHigh, in float noiseThresholdLow )
+{
+ float noise = ( time == 0.0 ) ? summedPerlinNoise( pos, terms, absoluteNoise ) : summedPerlinNoise( vec4( pos, time ), terms, absoluteNoise );
+ if ( turbulenceWeight != vec3( 0.0, 0.0, 0.0 ) )
+ {
+ noise = sin( dot( pos, turbulenceWeight ) + noise );
+ }
+ if ( ! absoluteNoise )
+ {
+ noise = 0.5 * noise + 0.5; // scale [-1,1] to [0,1]
+ }
+ if ( applyMarble )
+ {
+ noise = cos( pos.x + 5.0 * noise ); // classic Perlin marble function, with magic 5.0
+ }
+ if ( applyDent )
+ {
+ noise = cube( noise );
+ }
+ if ( noiseBands != 1.0 )
+ {
+ // Create banding/stripes by using the fraction component only
+ noise *= noiseBands;
+ noise -= floor( noise );
+ noise += pow( 1.0 - noise, 20.0 );
+ }
+ if ( noiseThresholdLow < noiseThresholdHigh )
+ {
+ // clamp the noise
+ noise = clamp( ( noise - noiseThresholdLow ) / ( noiseThresholdHigh - noiseThresholdLow ), 0.0, 1.0 );
+ }
+ return( noise );
+}
+
diff --git a/res/effectlib/perlinNoiseBumpTexture.glsllib b/res/effectlib/perlinNoiseBumpTexture.glsllib
new file mode 100644
index 0000000..6e0982f
--- /dev/null
+++ b/res/effectlib/perlinNoiseBumpTexture.glsllib
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec3 perlinNoiseBumpTexture( in texture_coordinate_info uvw, in float factor, in float size, in bool applyMarble
+ , in bool applyDent, in float noisePhase, in int noiseLevels, in bool absoluteNoise, in vec3 noiseDistortion
+ , in float noiseThresholdHigh, in float noiseThresholdLow, in float noiseBands, in vec3 normal )
+{
+ float delta = 0.1 / noiseBands;
+ vec3 pos = uvw.position / size;
+
+ float r0 = perlinNoise( pos, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r1 = perlinNoise( pos + delta * uvw.tangent_u, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r2 = perlinNoise( pos + delta * uvw.tangent_v, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ float r3 = perlinNoise( pos + delta * normal, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+
+ return( normalize( normal - factor * ( ( r1 - r0 ) * uvw.tangent_u + ( r2 - r0 ) * uvw.tangent_v + ( r3 - r0 ) * normal ) ) );
+}
+
diff --git a/res/effectlib/perlinNoiseTexture.glsllib b/res/effectlib/perlinNoiseTexture.glsllib
new file mode 100644
index 0000000..d968403
--- /dev/null
+++ b/res/effectlib/perlinNoiseTexture.glsllib
@@ -0,0 +1,11 @@
+texture_return perlinNoiseTexture( in texture_coordinate_info uvw, in vec3 color1, in vec3 color2, in float size, in bool applyMarble, in bool applyDent
+ , in float noisePhase, in int noiseLevels, in bool absoluteNoise, in vec3 noiseDistortion
+ , in float noiseThresholdHigh, in float noiseThresholdLow, in float noiseBands )
+{
+ float noise = perlinNoise( uvw.position / size, noisePhase, noiseLevels, noiseDistortion, absoluteNoise
+ , applyMarble, applyDent, noiseBands, noiseThresholdLow, noiseThresholdHigh );
+ texture_return tr;
+ tr.tint = mix( color1, color2, noise );
+ tr.mono = average( tr.tint );
+ return( tr );
+}
diff --git a/res/effectlib/physGlossyBSDF.glsllib b/res/effectlib/physGlossyBSDF.glsllib
new file mode 100644
index 0000000..ece836b
--- /dev/null
+++ b/res/effectlib/physGlossyBSDF.glsllib
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 PHYS_GLOSSY_BSDF_GLSLLIB
+#define PHYS_GLOSSY_BSDF_GLSLLIB 1
+
+float sqr(float v)
+{
+ return v*v;
+}
+
+float Gterm( float cosTheta, float roughness )
+{
+ float k = roughness * 0.31830988618; // roughness / pi
+ return clamp( ( cosTheta / (cosTheta*(1.0-k) + k) + (1.0 - k*k) ) * 0.5, 0.0, 1.0 );
+}
+
+
+// PKC -- I came up with an anisotropic microfacet BSDF that has some superficial similarity to GGX in
+// its appearance, but is far simpler and more compact in its implementation. It uses a Cauchy-like lobe
+// shape and because it has an analytic solution to its antiderivative, we can compute the integral given
+// the support boundaries. It's also possible to importance sample at perfect efficiency.
+// This is generally a good choice for any material which has a polish coating to it.
+// TODO : The way roughness scales with this BSDF is roughly equivalent to roughness^2 would affect Ward.
+// It's debatable whether we want that to be done as a sqrt here or as square in Ward.
+vec4 kggxGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
+ vec3 H = normalize(L + V);
+
+ // NOTE : This BSDF allows roughness up to 2.0 which allows it
+ // to trend partially into Oren-Nayar diffuse territory, but we should
+ // assume that anything that falls under "glossy" should still be
+ // in the range of 0..1
+ float ax = clamp(roughnessU, 0.0001, 2.0);
+ float ay = clamp(roughnessV, 0.0001, 2.0);
+
+ float NdotL = dot(tanFrame[2], L);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+
+ // if (0.0 < NdotL)
+ // {
+ vec3 Haf = L + V;
+
+ float HdotN = clamp( dot(H, tanFrame[2]), 0.0001, 1.0 );
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ float sigma = sqrt(ax * ay);
+ float sigma2 = ax * ay * HdotN;
+
+ float thetaI = acos( dot(V, tanFrame[2]) );
+ float maxThetaI = (thetaI + 1.57079632679) * 0.5;
+ float minThetaI = (thetaI - 1.57079632679) * 0.5;
+ float range = atan(maxThetaI / sigma) - atan(minThetaI / sigma);
+ range = max( range, ax*ay );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float PDF = sigma2 / (sigma2 + sqr(HdotX / ax) + sqr(HdotY / ay));
+ PDF *= dot(Haf, Haf) / (4.71238898038 * sqr(dot(Haf, L)) * ax*ay * sigma * sqr(range));
+
+ rgba.rgb = Gterm(HdotL, sigma) * lightSpecular * PDF * max(NdotL, 0.0);
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+// }
+ return rgba;
+}
+
+vec4 kggxGlossyDefaultMtl( in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, in vec3 lightSpecular,
+ in vec3 materialSpecular, in float roughU, in float roughV )
+{
+ vec3 bitan = normalize(cross(normal, tangent));
+ mat3 tanFrame = mat3( normalize(cross( bitan, normal) ), bitan, normal );
+ return vec4(materialSpecular, 1.0) * kggxGlossyBSDF( tanFrame, L, V, lightSpecular, 1.5, roughU, roughV, scatter_reflect );
+}
+
+// To be exact, this is not the Ward lobe as Ward originally described (there are a few flaws in
+// the original paper, which had spawned half a dozen corrective measures as papers of their own).
+// This is a Ward-Duer variant with Geisler-Moroder's modified normalization factor which serves
+// to bound the albedo.
+vec4 wardGlossyBSDF( in mat3 tanFrame, in vec3 L, in vec3 V, in vec3 lightSpecular, in float ior,
+ in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
+ vec3 H = normalize(L + V);
+
+ // specular
+ float ax = clamp(roughnessU, 0.0001, 1.0);
+ float ay = clamp(roughnessV, 0.0001, 1.0);
+
+ float NdotL = dot(tanFrame[2], L);
+ float HdotL = clamp(dot(H, L), 0.0, 1.0);
+
+// if (0.0 < NdotL)
+// {
+ vec3 Haf = L + V;
+
+ float HdotN = clamp( dot(H, tanFrame[2]), 0.0001, 1.0 );
+ float HdotX = clamp( abs(dot(H, tanFrame[0])), 0.0001, 1.0 );
+ float HdotY = clamp( abs(dot(H, tanFrame[1])), 0.0001, 1.0 );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ float exponent = -(sqr(HdotX/ax) + sqr(HdotY/ay));
+ exponent /= sqr(HdotN);
+ float PDF = exp(exponent) / (4.0 * 3.1415926535 * ax * ay);
+ PDF *= 4.0 * dot(Haf, Haf) / sqr(sqr(dot(Haf,tanFrame[2])));
+
+ rgba.rgb = Gterm(HdotL, sqrt(ax * ay)) * lightSpecular * PDF * max(NdotL, 0.0);
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ rgba.a = pow(1.0 - clamp(HdotL, 0.0, 1.0), 5.0);
+ }
+// }
+ return rgba;
+}
+
+vec4 wardGlossyDefaultMtl( in vec3 normal, in vec3 tangent, in vec3 L, in vec3 V, in vec3 lightSpecular,
+ in vec3 materialSpecular, in float roughU, in float roughV )
+{
+ vec3 bitan = normalize(cross(normal, tangent));
+ mat3 tanFrame = mat3( normalize(cross( bitan, normal) ), bitan, normal );
+ return vec4(materialSpecular, 1.0) * wardGlossyBSDF( tanFrame, L, V, lightSpecular, 1.5, roughU, roughV, scatter_reflect );
+}
+
+#endif
diff --git a/res/effectlib/random255.glsllib b/res/effectlib/random255.glsllib
new file mode 100644
index 0000000..ef586a7
--- /dev/null
+++ b/res/effectlib/random255.glsllib
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// random [0..255] calculated by some simple Linear Congruential Generator (LCG)
+// Verfied, that each function is just a permutation of {0,...,255}, that is, with 0<=x<=255, each value in [0,255] is returned once
+int random255X( in int x )
+{
+ return( ( ( 8365 * ( x & 0xFF ) + 32285 ) >> 0 ) & 0xFF );
+}
+
+int random255Y( in int x )
+{
+ return( ( ( 3152 * ( x & 0xFF ) + 11819 ) >> 4 ) & 0xFF );
+}
+
+int random255Z( in int x )
+{
+ return( ( ( 119 * ( x & 0xFF ) + 18747 ) >> 0 ) & 0xFF );
+}
+
+int random255W( in int x )
+{
+ return( ( ( 26814 * ( x & 0xFF ) + 9642 ) >> 1 ) & 0xFF );
+}
+
+ivec3 random255XYZ( in ivec3 xyz )
+{
+ return( ivec3( random255X( xyz.x ), random255Y( xyz.y ), random255Z( xyz.z ) ) );
+}
diff --git a/res/effectlib/refraction.glsllib b/res/effectlib/refraction.glsllib
new file mode 100644
index 0000000..f961c50
--- /dev/null
+++ b/res/effectlib/refraction.glsllib
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+// this is entirly phiysical incorrect
+// We just use this to fake distortion when we have no environment available
+// The displacement is calculated on ior
+vec3 refraction( in sampler2D sampler, in float materialIOR )
+{
+ vec3 displace = fresnel( viewDir, vec3( materialIOR ));
+
+ float xdir = abs( viewDir.x );
+ float ydir = abs( viewDir.y );
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ vec2 newUV = vec2(gl_FragCoord.xy/texSize);
+ if ( xdir > ydir)
+ {
+ newUV = ( viewDir.x > 0.0) ? newUV + displace.xy : newUV - displace.xy;
+ }
+ else
+ {
+ newUV = ( viewDir.y > 0.0) ? newUV - displace.xy : newUV + displace.xy;
+ }
+
+ vec3 refractColor = texture( sampler, newUV ).rgb;
+
+ return refractColor;
+}
+
+// This should really not be used, but it's there for the sake of testing.
+vec3 refractBlur( in sampler2D sampler, in vec3 viewDir, in float materialIOR, in float blurWidth )
+{
+ // This is really terrible, but at least is a little better than
+ vec3 displace = viewDir * materialIOR;
+
+ vec2 texSize = vec2( textureSize( sampler, 0 ) );
+ texSize = vec2(1.0) / texSize;
+ vec2 newUV = vec2(gl_FragCoord.xy * texSize);
+ newUV += displace.xy * 0.005;
+
+ //vec3 refractColor = texture( sampler, newUV ).rgb;
+ vec3 refractColor = vec3(0);
+ int sz = int(ceil(blurWidth));
+ float wtsum = 0.0;
+
+ for (int y = -sz; y <= sz; ++y)
+ {
+ for (int x = -sz; x <= sz; ++x)
+ {
+ float wt = float(x*x + y*y) / (blurWidth * 0.5);
+ wt = exp2(-wt);
+ //refractColor += wt * textureOffset( sampler, newUV, ivec2(x, y) ).rgb;
+ vec2 uvOfs = vec2(x, y) * texSize;
+ refractColor += wt * texture( sampler, newUV+uvOfs).rgb;
+ wtsum += wt;
+ }
+ }
+
+ return refractColor / wtsum;
+}
diff --git a/res/effectlib/rotationTranslationScale.glsllib b/res/effectlib/rotationTranslationScale.glsllib
new file mode 100644
index 0000000..78bb8dd
--- /dev/null
+++ b/res/effectlib/rotationTranslationScale.glsllib
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 ROTATION_TRANSLATION_SCALE_GLSLLIB
+#define ROTATION_TRANSLATION_SCALE_GLSLLIB
+
+mat4 rotationTranslationScale( in vec3 rotation, in vec3 translation, in vec3 scaling )
+{
+ mat4 st = mat4( scaling.x, 0.0, 0.0, 0.0
+ , 0.0, scaling.y, 0.0, 0.0
+ , 0.0, 0.0, scaling.z, 0.0
+ , translation.x - 0.5, translation.y - 0.5, translation.z - 0.5, 1.0 );
+ vec3 s = sin( rotation );
+ vec3 c = cos( rotation );
+ mat4 r = mat4( c.y * c.z, -c.x * s.z + s.x * s.y * c.z, s.x * s.z + c.x * s.y * c.z, 0.0
+ , c.y * s.z, c.x * c.z + s.x * s.y * s.z, -s.x * c.z + c.x * s.y * s.z, 0.0
+ , -s.y , s.x * c.y , c.x * c.y , 0.0
+ , 0.5 , 0.5 , 0.5 , 1.0 );
+ return( st * r );
+}
+
+
+#endif
diff --git a/res/effectlib/sampleArea.glsllib b/res/effectlib/sampleArea.glsllib
new file mode 100644
index 0000000..01f3a74
--- /dev/null
+++ b/res/effectlib/sampleArea.glsllib
@@ -0,0 +1,180 @@
+/****************************************************************************
+**
+** 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_AREA_GLSLLIB
+#define SAMPLE_AREA_GLSLLIB 1
+
+#include "funcareaLightVars.glsllib"
+#include "funccalculateDiffuseAreaOld.glsllib"
+#include "funcsampleAreaGlossyDefault.glsllib"
+
+float rand1d(vec2 n)
+{
+ return 0.5 + 0.5 * fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
+}
+
+vec3 quatRotate( vec4 q, vec3 v )
+{
+ return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
+}
+
+vec3 lightUVToRay( in vec3 pos, in vec3 lightPos, in mat3 lightFrame, in float width, in float height, in vec2 uv )
+{
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ vec3 hitPos = lightPos + (uv.x - 0.5) * width * lightFrame[0] + (uv.y - 0.5) * height * lightFrame[1];
+ return normalize(hitPos - pos);
+}
+
+// This is usable only for planar rectangular lights. Will need to break this down into different paths for different shapes.
+float getUVHitBounds( in vec3 pos, in mat3 lightFrame, in vec3 lightPos, in float width, in float height, in vec3 V0, in vec3 V1, in vec3 V2, in vec3 V3, out vec2 UVmin, out vec2 UVmax )
+{
+ float d0 = dot( lightPos, lightFrame[2] );
+ float d1 = dot( pos, lightFrame[2] );
+
+ // If the point is behind the light, it can't be illuminated.
+ if (d0 < d1)
+ {
+ UVmin = vec2( -1.0, -1.0 );
+ UVmax = vec2( -1.0, -1.0 );
+ return 0.0;
+ }
+
+ // Compute where all the rays of the light beam hit the light plane
+ float t[4];
+ vec3 v[4];
+
+ v[0] = V0; v[1] = V1; v[2] = V2; v[3] = V3;
+ t[0] = (d0 - d1) / dot(V0, lightFrame[2]);
+ t[1] = (d0 - d1) / dot(V1, lightFrame[2]);
+ t[2] = (d0 - d1) / dot(V2, lightFrame[2]);
+ t[3] = (d0 - d1) / dot(V3, lightFrame[2]);
+
+ UVmin = vec2(1e6, 1e6);
+ UVmax = vec2(-1e6, -1e6);
+
+ // If any of them are "negative" relative to the ray direction
+ // We don't want to consider them.
+ bool weight[4];
+ float wtsum = 0.0;
+ weight[0] = (t[0] > 0.0);
+ weight[1] = (t[1] > 0.0);
+ weight[2] = (t[2] > 0.0);
+ weight[3] = (t[3] > 0.0);
+
+ width *= dot(lightFrame[0], lightFrame[0]);
+ height *= dot(lightFrame[1], lightFrame[1]);
+
+ for (int i = 0; i < 4; ++i)
+ {
+ vec3 curPos = pos + v[i] * t[i];
+ curPos -= lightPos;
+ vec2 curUV = vec2( dot(curPos, lightFrame[0]) / width, dot(curPos, lightFrame[1]) / height ) + vec2(0.5);
+
+ UVmin = min(UVmin, curUV); UVmax = max(UVmax, curUV);
+ wtsum += weight[i] ? 0.25 : 0.0;
+ }
+
+ return wtsum;
+}
+
+// Shooting a narrow beam, and then scaling up that beam based on the actual roughness
+vec4 sampleAreaGlossy( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec3 viewDir, in float roughU, in float roughV )
+{
+ float sigmaU = clamp( 0.5 * roughU, 0.005, 0.5 );
+ float sigmaV = clamp( 0.5 * roughV, 0.005, 0.5 );
+ vec2 UVset[5];
+
+ mat3 lightFrame = mat3( arealights[lightIdx].right.xyz, arealights[lightIdx].up.xyz, -arealights[lightIdx].direction.xyz );
+
+ 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, arealights[lightIdx].position.xyz, lightFrame,
+ arealights[lightIdx].right.w, arealights[lightIdx].up.w, 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] += UVset[4]; UVset[1] += UVset[4];
+ UVset[2] += UVset[4]; UVset[3] += UVset[4];
+
+ vec2 UVmin = UVset[4], UVmax = UVset[4];
+ vec2 cminUV, cmaxUV;
+ UVmin = min(UVmin, UVset[0]); UVmax = max(UVmax, UVset[0]);
+ UVmin = min(UVmin, UVset[1]); UVmax = max(UVmax, UVset[1]);
+ 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) );
+
+ vec2 hitScale = (cmaxUV - cminUV);
+ vec2 fullScale = (UVmax - UVmin);
+ float intensity = ( hitScale.x * hitScale.y ) / max( fullScale.x * fullScale.y, 0.0001 );
+
+ return vec4( wt * intensity );
+}
+
+vec4 sampleAreaDiffuse( in mat3 tanFrame, in vec3 pos, in int lightIdx )
+{
+ float intensity = 0.0;
+ vec3 finalDir;
+ intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
+ intensity *= clamp( dot(finalDir, tanFrame[2]), 0.0, 1.0 );
+ return vec4( intensity );
+}
+
+vec4 sampleAreaDiffuseTransmissive( in mat3 tanFrame, in vec3 pos, in int lightIdx, in vec4 transmissiveColor, in float translucentFalloff, float lightWrap )
+{
+ float intensity = 0.0;
+ vec3 finalDir;
+ intensity = calculateDiffuseAreaOld( arealights[lightIdx].direction.xyz, arealights[lightIdx].position.xyz,
+ arealights[lightIdx].up, arealights[lightIdx].right, pos, finalDir );
+ intensity *= clamp( dot(finalDir, -tanFrame[2]), 0.0, 1.0 );
+
+ float l = 0.2126 * transmissiveColor.r + 0.7152 * transmissiveColor.g + 0.0722 * transmissiveColor.b;
+
+ float I = max( 0.0, ((dot(finalDir, -tanFrame[2]) + lightWrap)/ (1.0 + lightWrap)) );
+ float translucent_thickness = l * l;
+ float translucent_thickness_exp = exp( translucent_thickness * translucentFalloff) * I;
+
+ return vec4( translucent_thickness_exp * intensity );
+}
+
+#endif
diff --git a/res/effectlib/sampleLight.glsllib b/res/effectlib/sampleLight.glsllib
new file mode 100644
index 0000000..05ad5b4
--- /dev/null
+++ b/res/effectlib/sampleLight.glsllib
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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_LIGHT_GLSLLIB
+#define SAMPLE_LIGHT_GLSLLIB
+
+#define MAX_NUM_SHADOWS 8
+
+#ifndef QT3DS_ENABLE_SSM
+#define QT3DS_ENABLE_SSM 0
+#endif
+
+#include "SSAOCustomMaterial.glsllib"
+#if QT3DS_ENABLE_SSM
+#include "shadowMapping.glsllib"
+#endif
+
+#include "funcsampleLightVars.glsllib"
+
+#if QT3DS_ENABLE_SSM
+uniform sampler2D shadowMaps[MAX_NUM_SHADOWS];
+uniform samplerCube shadowCubes[MAX_NUM_SHADOWS];
+uniform int uNumShadowMaps;
+uniform int uNumShadowCubes;
+#endif
+
+void sampleLight(in LightSource light,
+ in vec3 pos,
+ out vec3 wi,
+ out vec3 opAmbient,
+ out vec3 opDiffuse,
+ out vec3 opSpecular)
+{
+ float att = 1.0;
+ if (light.position.w == 0.0) // directional light
+ {
+ wi = normalize(light.position.xyz);
+#if QT3DS_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleOrthographic( shadowMaps[light.shadowIdx], light.shadowControls, light.shadowView, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ else if (light.width > 0.01 && light.height > 0.01) // area light
+ {
+ // This approach is based on the 1994 Tech Report by James Arvo --
+ // The Irradiance Jacobian for Partially Occluded Polyhedral Sources
+ // The nice thing about this approach is that it extends to arbitrary geometry (if we choose to support it),
+ // and accounts for distance & geometric attenuation automatically.
+ // Downsides -- only really works for diffuse reflection, does not account properly for an area light that
+ // intersects its receiver, in which case it illuminates as if the light source is two-sided Lambertian emitter.
+ vec3 v0 = light.position.xyz - (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);
+ vec3 v1 = light.position.xyz - (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
+ vec3 v2 = light.position.xyz + (light.right.xyz * light.width * 0.5) + (light.up.xyz * light.height * 0.5);
+ vec3 v3 = light.position.xyz + (light.right.xyz * light.width * 0.5) - (light.up.xyz * light.height * 0.5);
+
+ v0 = normalize( v0 - pos ); v1 = normalize( v1 - pos ); v2 = normalize( v2 - pos ); v3 = normalize( v3 - pos );
+
+ float a01 = acos( clamp( dot(v0, v1), -1.0, 1.0 ) );
+ float a12 = acos( clamp( dot(v1, v2), -1.0, 1.0 ) );
+ float a23 = acos( clamp( dot(v2, v3), -1.0, 1.0 ) );
+ float a30 = acos( clamp( dot(v3, v0), -1.0, 1.0 ) );
+
+ wi = vec3( 0.0 );
+ wi -= normalize(cross( v0, v1 )) * a01;
+ wi -= normalize(cross( v1, v2 )) * a12;
+ wi -= normalize(cross( v2, v3 )) * a23;
+ wi -= normalize(cross( v3, v0 )) * a30;
+
+ att = length(wi) * 0.15915494309; // solid angle / 2*pi
+ wi = normalize(wi);
+ att *= clamp( dot( pos - light.position.xyz, light.direction.xyz ), 0.0, 1.0 );
+#if QT3DS_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ else // point or spot light
+ {
+ wi = light.position.xyz - pos;
+ float dist = length(wi);
+ wi = wi / dist; // == normalize(wi);
+ att = 1.0 / (light.constantAttenuation + (light.linearAttenuation + light.quadraticAttenuation * dist) * dist);
+ /*
+ if (light.spotCutoff < 180.0) // spot light
+ {
+ float spot = max(0.0, dot(wi, -light.direction.xyz));
+ att *= (spot >= cos(light.spotCutoff * PI / 180.0)) ? pow(spot, light.spotExponent) : 0.0;
+ }
+ */
+#if QT3DS_ENABLE_SSM
+ if ( light.shadowIdx >= 0 )
+ att *= sampleCubemap( shadowCubes[light.shadowIdx], light.shadowControls, light.shadowView, light.position.xyz, pos, vec2(1.0, light.shadowControls.z) );
+#endif
+ }
+ float shadow = customMaterialShadow( -light.direction.xyz, pos );
+ opAmbient = att * light.ambient.xyz;
+ opDiffuse = att * shadow * light.diffuse.xyz;
+ opSpecular = att * shadow * light.specular.xyz;
+}
+
+#include "sampleArea.glsllib"
+
+#endif
diff --git a/res/effectlib/sampleProbe.glsllib b/res/effectlib/sampleProbe.glsllib
new file mode 100644
index 0000000..6556e51
--- /dev/null
+++ b/res/effectlib/sampleProbe.glsllib
@@ -0,0 +1,473 @@
+/****************************************************************************
+**
+** 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
+
+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
+
+#if QT3DS_ENABLE_LIGHT_PROBE_2
+uniform sampler2D light_probe2;
+uniform vec4 light_probe2_props;
+#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 = vec2(atan(smpDir.x, smpDir.z), asin(smpDir.y));
+ // assume equirectangular HDR spherical map (instead of cube map) and warp sample
+ // UV coordinates accordingly
+ smpUV *= 2.0 * vec2(0.1591596371160, 0.318319274232054);
+ // Default FOV is 180 deg = pi rad. Narrow the FOV
+ // by scaling texture coordinates by the ratio of
+ // incoming FOV to 180 degrees default
+ smpUV *= 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 = 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);
+
+ 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;
+}
+
+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 = 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;
+ }
+
+ 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/screenSpaceAO.glsllib b/res/effectlib/screenSpaceAO.glsllib
new file mode 100644
index 0000000..54204a1
--- /dev/null
+++ b/res/effectlib/screenSpaceAO.glsllib
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** 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 SCREEN_SPACE_AO_GLSLLIB
+#define SCREEN_SPACE_AO_GLSLLIB 1
+
+#include "depthpass.glsllib"
+
+
+float hashRot(vec2 pos)
+{
+ // Basically an odd-even hash.
+ float px = 2.0 * fract(floor(pos.x) * 0.5);
+ float py = fract(floor(pos.y) * 0.5);
+
+ return px + py;
+}
+
+vec3 quatRotate( vec4 q, vec3 v )
+{
+ return v + 2.0 * cross( cross( v, q.xyz ) + q.w * v, q.xyz );
+}
+
+vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
+ return vec3(scaledUV * sampleDepth, sampleDepth);
+}
+
+vec2 computeDir( vec2 baseDir, int v )
+{
+ float ang = 3.1415926535 * hashRot( gl_FragCoord.xy ) + float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+vec2 offsetDir( vec2 baseDir, int v )
+{
+ float ang = float(v - 1);
+ vec2 vX = vec2(cos(ang), sin(ang));
+ vec2 vY = vec2(-sin(ang), cos(ang));
+
+ return vec2( dot(baseDir, vX), dot(baseDir, vY) );
+}
+
+float SSambientOcclusion(sampler2D depthSampler, vec3 viewNorm, vec4 aoParams, vec4 aoParams2, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+{
+ float ret = 0.0;
+
+ vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
+ vec3 viewPos = getViewSpacePos( depthSampler, camProps, centerUV, UvToEye );
+ viewPos += viewNorm * aoParams.w;
+
+ float screenRadius = aoParams.y * aoScreen.y / viewPos.z;
+ if (screenRadius < 1.0) { return 1.0; }
+
+ vec3 kernel[9];
+
+ // The X and Y are the 2d direction, while the Z is the height of the sphere at that point.
+ // In essence, it normalizes the 3d vector, but we're really interested in the 2D offset.
+ kernel[0] = vec3(-0.1376476, 0.2842022, 0.948832);
+ kernel[1] = vec3(-0.626618, 0.4594115, 0.629516);
+ kernel[2] = vec3(-0.8903138, -0.05865424, 0.451554);
+ kernel[3] = vec3(0.2871419, 0.8511679, 0.439389);
+ kernel[4] = vec3(-0.1525251, -0.3870117, 0.909372);
+ kernel[5] = vec3(0.6978705, -0.2176773, 0.682344);
+ kernel[6] = vec3(0.7343006, 0.3774331, 0.5642);
+ kernel[7] = vec3(0.1408805, -0.88915, 0.4353);
+ kernel[8] = vec3(-0.6642616, -0.543601, 0.5130);
+
+ int radLevels = int(floor(aoParams2.x));
+ float radStep = 1.0 / aoParams2.x;
+
+ for (int j = 1; j <= radLevels; ++j)
+ {
+ for (int i = 0; i < 9; ++i)
+ {
+ float curRange = aoParams.y * radStep * float(j);
+ float curRadius = curRange * kernel[i].z;
+
+ vec3 smpDir;
+ smpDir.xy = computeDir(kernel[i].xy, j) * aoParams2.y + (1.0 - aoParams2.y) * offsetDir(kernel[i].xy, j);
+ smpDir.z = kernel[i].z;
+ smpDir *= curRange;
+
+ vec2 smpUV = centerUV.xy + smpDir.xy * aoScreen.zw;
+
+ // First method is based on Horizon-Based AO
+ vec3 samplePos = getViewSpacePos( depthSampler, camProps, smpUV, UvToEye );
+ vec3 smpVec = samplePos - viewPos;
+
+ float lenRad = dot(smpVec, smpVec);
+ smpVec = normalize(smpVec);
+ float lenDot = dot(smpVec, viewNorm);
+
+ lenRad /= aoParams.y*aoParams.y;
+ float falloff = smoothstep(8.0, 0.0, (lenRad - 1.0) * 0.125);
+ float occl = 1.0 - clamp(lenDot * falloff, 0.0, 1.0);
+
+ ret += occl * occl;
+ }
+ }
+
+ ret = (ret) / (9.0 * float(radLevels));
+
+ // Blend between soft and hard based on softness param
+ // NOTE : the 0.72974 is actually an gamma-inverted 0.5 (assuming gamma 2.2)
+ // Would not need this if we linearized color instead.
+ float hardCut = (1.0 - aoParams.z) * 0.72974;
+ ret = smoothstep(0.0, 1.0, (ret - hardCut) / (1.0 - hardCut));
+
+ // Blend between full and no occlusion based on strength param
+ ret = aoParams.x * ret + (1.0 - aoParams.x);
+
+ return ret;
+}
+
+#endif
diff --git a/res/effectlib/screenSpaceDO.glsllib b/res/effectlib/screenSpaceDO.glsllib
new file mode 100644
index 0000000..2ccc69f
--- /dev/null
+++ b/res/effectlib/screenSpaceDO.glsllib
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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 SCREEN_SPACE_DO_GLSLLIB
+#define SCREEN_SPACE_DO_GLSLLIB 1
+
+#include "depthpass.glsllib"
+
+vec3 getViewSpacePos( sampler2D depthSampler, vec2 camProps, vec2 UV, vec4 UvToEye )
+{
+ float sampleDepth = getDepthValue( texture(depthSampler, UV), camProps );
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ vec2 scaledUV = (UV * UvToEye.xy) + UvToEye.zw;
+ return vec3(scaledUV * sampleDepth, sampleDepth);
+}
+
+float shadowOcclusion(sampler2D depthSampler, vec3 lightDir, vec3 worldPos, mat4 viewMat, mat4 viewProj, vec4 shadowParams, vec2 camProps, vec4 aoScreen, vec4 UvToEye)
+{
+ vec3 viewPos = getViewSpacePos( depthSampler, camProps, ( gl_FragCoord.xy * aoScreen.zw ), UvToEye );
+ float depth = viewPos.z;
+
+ // Get the screen-space UV
+ vec2 centerUV = gl_FragCoord.xy * aoScreen.zw;
+
+ float screenDist = shadowParams.y * 3.1415926535 * aoScreen.y / viewPos.z;
+ if (screenDist < 1.0) { return 1.0; }
+
+ vec3 viewL = normalize( (viewMat * vec4(lightDir, 0)).xyz );
+
+ float steps = min( screenDist, 20.0 );
+ int maxCt = int(steps);
+ float step = 3.1415926535 * shadowParams.y / float(maxCt);
+ float ret = float(maxCt);
+
+ for( int i = 0; i < maxCt; ++i )
+ {
+ vec3 ray = lightDir * step * float(i);
+ vec3 samplePos = worldPos - ray;
+
+ vec4 smpUV = viewProj * vec4(samplePos, 1.0);
+ smpUV /= smpUV.w;
+ smpUV.xy = (smpUV.xy + 1.0) * 0.5;
+
+ vec3 testPos = getViewSpacePos( depthSampler, camProps, smpUV.xy, UvToEye );
+ testPos.z += shadowParams.w;
+ vec3 testVec = normalize(viewPos - testPos);
+ testVec -= viewL;
+ float isBehind = clamp( testVec.z, 0.0, 1.0 );
+ float diff = (testPos.z - depth) / shadowParams.y;
+ ret -= isBehind * (1.0 / (1.0 + diff * diff));
+ }
+
+ ret /= float(maxCt); // divide by number of samples;
+ // Blend between soft and hard based on softness param
+ // NOTE : the 0.72974 is actually an gamma-inverted 0.5 (assuming gamma 2.2)
+ // Would not need this if we linearized color instead.
+ float hardCut = (ret <= 0.72974) ? 0.0 : 1.0;
+ ret = shadowParams.z * ret + (1.0 - shadowParams.z) * hardCut;
+
+ // Blend between full and no occlusion based on strength param
+ ret = shadowParams.x * ret + (1.0 - shadowParams.x);
+
+ return ret;
+}
+
+// For reference
+/*
+float glossyOcclusionBasis(sampler2D depthSampler, mat3 tanFrame, vec3 worldPos, mat4 viewProj, vec3 viewDir, vec4 shadowParams, vec2 camProps, float roughness)
+{
+ float ret = 16.0;
+
+ float kernel[16];
+ 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;
+
+ float rough = clamp(roughness, 0.0001, 1.0);
+ float normFac = 1.0 / (rough);
+
+ float phiShift = hashRot( gl_FragCoord.xy );
+ ivec2 iCoords = ivec2( gl_FragCoord.xy );
+ float depth = getDepthValue( texelFetch(depthSampler, iCoords, 0) );
+ depth = depthValueToLinearDistance( depth, camProps );
+
+ for( int i = 0; i < 16; ++i )
+ {
+ vec3 localDir;
+ float phi = 6.28318530718 * (kernel[i] + phiShift);
+ float cosTheta = sqrt( float(i+1) / 33.0);
+ localDir.z = sqrt(1.0 - cosTheta*cosTheta) * normFac;
+ localDir.x = cos(phi) * cosTheta;
+ localDir.y = sin(phi) * cosTheta;
+
+ localDir = normalize(localDir);
+
+ vec3 halfDir = tanFrame[0]*localDir.x + tanFrame[1]*localDir.y + tanFrame[2]*localDir.z;
+ vec3 ray = reflect( -viewDir, halfDir ) * shadowParams.x;
+
+ vec4 samplePos = vec4( worldPos + ray, 1.0 );
+
+ vec4 sampleProj = viewProj * samplePos;
+ sampleProj /= sampleProj.w;
+ sampleProj.xy = (sampleProj.xy + 1.0) * 0.5;
+ float sampleDepth = getDepthValue( texture(depthSampler, sampleProj.xy) );
+
+ sampleDepth = depthValueToLinearDistance( sampleDepth, camProps );
+
+ // Occlusion is applied based on a Cauchy distribution filter
+ // But with a "dead zone" for the very close samples. By subtracting it from 16,
+ // which represents no occlusion (16/16 = 1), we let nearby occluders have a
+ // lot of effect, but far away occluders do not. Furthermore, the "dead zone"
+ // in the filter means that the extremely near (which we assume to be part of the
+ // same surface) are also excluded to try and limit self-occlusion.
+ float occlDist = 4.0 * max(depth - sampleDepth - shadowParams.y, 0.0) / shadowParams.x;
+ float occlFactor = 1.0 / ( 1.0 + occlDist*occlDist*0.04 );
+ occlFactor -= 1.0 / ( 1.0 + occlDist*occlDist*4.0 );
+ ret -= min(2.0 * occlFactor, 1.0);
+ }
+
+ ret /= 16.0; // divide by number of samples;
+ return ret;
+}
+*/
+
+#endif
diff --git a/res/effectlib/shadowMapping.glsllib b/res/effectlib/shadowMapping.glsllib
new file mode 100644
index 0000000..df351f9
--- /dev/null
+++ b/res/effectlib/shadowMapping.glsllib
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** 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 SHADOW_MAPPING_GLSLLIB
+#define SHADOW_MAPPING_GLSLLIB
+
+#include "depthpass.glsllib"
+
+float sampleParaboloid( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps, out vec2 smpUV )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float ptDepth = depthValueToLinearDistance( 1.0 - smpCoord.z, cameraProps );
+ ptDepth = (ptDepth - cameraProps.x) / (cameraProps.y - cameraProps.x);
+ smpCoord = normalize( smpCoord.xyz );
+ smpCoord.xy /= -( smpCoord.z + 1.0 );
+ smpCoord.xy = vec2(1.0) - smpCoord.xy;
+ smpCoord.xy *= 0.5;
+
+ smpUV = smpCoord.xy; // This is just for debug purposes to ensure what the sampled UV cooord is.
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+ sampleDepth *= sampleDepth;
+ ptDepth *= ptDepth;
+ float shadowFac = min(1.0, exp(shadowControls.y * sampleDepth * sampleDepth) / exp(shadowControls.y * ptDepth * ptDepth));
+
+ smpUV.xy *= shadowFac;
+ return shadowFac;
+}
+
+float sampleCubemap( in samplerCube shadowCube, in vec4 shadowControls, in mat4 shadowViewMat, in vec3 lightPos, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec3 viewDir = worldPos - vec3(lightPos.x, lightPos.y, lightPos.z);
+ float ptDepth = length(viewDir.xyz);
+ vec4 viewCoord = shadowViewMat * vec4( viewDir.xyz, 0.0 );
+ viewCoord.xyz /= ptDepth;
+ ptDepth = clamp((ptDepth - 1.0) / (cameraProps.y - 1.0), 0.0, 1.0);
+
+ float smpDepth = texture( shadowCube, viewDir.xyz ).x + shadowControls.x;
+
+ float shadowFac = min(1.0, exp(shadowControls.y * smpDepth) / exp(shadowControls.y * ptDepth));
+ return shadowFac;
+}
+
+float sampleOrthographic( in sampler2D shadowMap, in vec4 shadowControls, in mat4 shadowMatrix, in vec3 worldPos, in vec2 cameraProps )
+{
+ vec4 projCoord = shadowMatrix * vec4( worldPos, 1.0 );
+ vec3 smpCoord = projCoord.xyz / projCoord.w;
+
+ float sampleDepth = texture( shadowMap, smpCoord.xy ).x + shadowControls.x;
+
+ return min(1.0, exp(shadowControls.y * sampleDepth) / exp(shadowControls.y * smpCoord.z));
+}
+
+
+struct ParaboloidMapResult
+{
+ vec4 m_Position;
+ vec4 m_WorldPos;
+};
+
+ParaboloidMapResult VertexParaboloidDepth(vec3 pos, mat4 inMVP)
+{
+ vec4 glPos = inMVP * vec4( pos, 1.0 );
+ glPos /= glPos.w;
+ glPos.xyz = normalize( glPos.xyz );
+ vec4 world_pos;
+ world_pos.w = glPos.z;
+ glPos.xy /= glPos.z + 1.0;
+ world_pos.xyz = pos.xyz;
+
+ ParaboloidMapResult retval;
+ retval.m_Position = glPos;
+ retval.m_WorldPos = world_pos;
+ return retval;
+}
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/shadowMappingFragment.glsllib b/res/effectlib/shadowMappingFragment.glsllib
new file mode 100644
index 0000000..660d736
--- /dev/null
+++ b/res/effectlib/shadowMappingFragment.glsllib
@@ -0,0 +1,10 @@
+#include "depthpass.glsllib"
+float FragmentParaboloidDepth( vec4 inWorldPos, mat4 inMVP, vec2 inCameraProperties )
+{
+ if (inWorldPos.w < 0.0)
+ discard;
+ vec4 projVec = inMVP * vec4( inWorldPos.xyz, 1.0 );
+ projVec /= projVec.w;
+ projVec.z = depthValueToLinearDistance( 1.0 - projVec.z, inCameraProperties );
+ return (projVec.z - inCameraProperties.x) / (inCameraProperties.y - inCameraProperties.x);
+}
diff --git a/res/effectlib/simpleGlossyBSDF.glsllib b/res/effectlib/simpleGlossyBSDF.glsllib
new file mode 100644
index 0000000..be6024c
--- /dev/null
+++ b/res/effectlib/simpleGlossyBSDF.glsllib
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 simpleGlossyBSDF( in mat3 tanFrame, in vec3 L, vec3 V, in vec3 lightSpecular, in float ior
+ , in float roughnessU, in float roughnessV, int mode )
+{
+ vec4 rgba = vec4( 0.0, 0.0, 0.0, 1.0 );
+
+ float cosTheta = dot( tanFrame[2], L );
+ if ( 0.0 < cosTheta )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+
+ if ( ( mode == scatter_reflect ) || ( mode == scatter_reflect_transmit ) )
+ {
+ vec3 R = reflect( -L, tanFrame[2] );
+ float cosine = dot( R, V );
+ float shine = ( 0.0 < cosine ) ? ( ( 0.0 < roughness ) ? pow( cosine, 1.0 / roughness ) : ( 0.9999 <= cosine ) ? 1.0 : 0.0 ) : 0.0;
+ rgba.rgb = shine * lightSpecular;
+ }
+ }
+ if ( ( mode == scatter_transmit ) || ( mode == scatter_reflect_transmit ) )
+ {
+ // check against total reflection
+ vec3 R = refract( -V, tanFrame[2], ior );
+ if ( R == vec3( 0.0, 0.0, 0.0 ) )
+ {
+ rgba.a = 1.0;
+ }
+ else
+ {
+ rgba.a = 0.0;
+ }
+ }
+
+ return( rgba );
+}
+
+vec4 simpleGlossyBSDFEnvironment( in mat3 tanFrame, in vec3 viewDir, in float roughnessU, in float roughnessV, int mode )
+{
+ vec3 rgb = vec3( 0.0, 0.0, 0.0 );
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ if ( uEnvironmentMappingEnabled )
+ {
+ float roughness = calculateRoughness( tanFrame[2], roughnessU, roughnessV, tanFrame[0] );
+ vec3 R = reflect( -viewDir, tanFrame[2] );
+ rgb = evalEnvironmentMap( R, roughness );
+ rgb = simpleGlossyBSDF( tanFrame, R, viewDir, rgb, 1.0, roughnessU, roughnessV, scatter_reflect ).rgb;
+ }
+#endif
+ return( vec4( rgb, 1.0 ) );
+}
+
+// RNM radiosity normal maps
+vec4 glossyRNM( in vec3 N, in vec3 rnmX, in vec3 rnmY, in vec3 rnmZ )
+{
+ // we use a fixed basis like Half Life
+ vec3 B0 = vec3( -0.40825, 0.70711, 0.57735);
+ vec3 B1 = vec3( -0.40825, -0.70711, 0.57735);
+ vec3 B2 = vec3( 0.8165, 0.0, 0.57735);
+
+ vec3 dp;
+ dp.x = clamp( dot ( N , B0 ), 0.0, 1.0);
+ dp.y = clamp( dot ( N , B1 ), 0.0, 1.0);
+ dp.z = clamp( dot ( N , B2 ), 0.0, 1.0);
+
+ float sum = 1.0 / dot( dp, vec3(1.0, 1.0, 1.0) );
+ vec3 diffuseLight = dp.x * rnmX + dp.y * rnmY + dp.z * rnmZ;
+ //vec3 diffuseLight = N.x * rnmX + N.y * rnmY + N.z * rnmZ;
+
+ return (vec4(diffuseLight, 1.0) * sum);
+}
diff --git a/res/effectlib/specularBSDF.glsllib b/res/effectlib/specularBSDF.glsllib
new file mode 100644
index 0000000..78e541a
--- /dev/null
+++ b/res/effectlib/specularBSDF.glsllib
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#include "funcspecularBSDF.glsllib"
+
+#ifndef DEFAULT_MATERIAL_LIGHTING
+
+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 ) );
+}
+
+#endif
diff --git a/res/effectlib/spotEdf.glsllib b/res/effectlib/spotEdf.glsllib
new file mode 100644
index 0000000..2abe194
--- /dev/null
+++ b/res/effectlib/spotEdf.glsllib
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float spotEdf( float exponent )
+{
+ float att = 1.0;
+
+ float dist = length(viewDir);
+ vec3 spotDir = viewDir / dist;
+
+ float spot = max(0.0, dot(spotDir, normal));
+ att = pow(spot, exponent);
+
+ return att;
+}
diff --git a/res/effectlib/square.glsllib b/res/effectlib/square.glsllib
new file mode 100644
index 0000000..9685722
--- /dev/null
+++ b/res/effectlib/square.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+float square( in float x )
+{
+ return( x * x );
+}
+
diff --git a/res/effectlib/tangentSpaceNormalTexture.glsllib b/res/effectlib/tangentSpaceNormalTexture.glsllib
new file mode 100644
index 0000000..1fcc429
--- /dev/null
+++ b/res/effectlib/tangentSpaceNormalTexture.glsllib
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 FILE_NORMAL_TEXTURE_GLSLLIB
+#define FILE_NORMAL_TEXTURE_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+
+#include "luminance.glsllib"
+#include "monoChannel.glsllib"
+#include "textureCoordinateInfo.glsllib"
+#define wrap_clamp 0
+#define wrap_repeat 1
+#define wrap_mirrored_repeat 2
+#include "rotationTranslationScale.glsllib"
+#include "transformCoordinate.glsllib"
+
+#endif
+
+//interpreting the color values of a bitmap as a vector in tangent space
+vec3 tangentSpaceNormalTexture( in sampler2D tex, in float factor, in bool flipTangentU, in bool flipTangentV
+ , in texture_coordinate_info uvw, in vec2 cropU, in vec2 cropV, in int wrapU, in int wrapV )
+{
+ // if we mirror repeat a tangent space texture, tangent space needs to be flipped for every other tile
+ bool flipU = flipTangentU;
+ bool flipV = flipTangentV;
+ if ( wrapU == wrap_mirrored_repeat )
+ {
+ if ( ( ( 0.0 < uvw.position.x ) && ( int( uvw.position.x ) % 2 == 1 ) )
+ || ( ( uvw.position.x < 0.0 ) && ( int( uvw.position.x ) % 2 == 0 ) ) )
+ {
+ flipU = !flipU;
+ }
+ if ( ( ( 0.0 < uvw.position.y ) && ( int( uvw.position.y ) % 2 == 1 ) )
+ || ( ( uvw.position.y < 0.0 ) && ( int( uvw.position.y ) % 2 == 0 ) ) )
+ {
+ flipV = !flipV;
+ }
+ }
+
+ vec3 tangent = 2.0 * texture( tex, uvw.position.xy ).xyz - 1.0;
+
+ vec3 tangentU = normalize( flipU ? -uvw.tangent_u : uvw.tangent_u );
+ vec3 tangentV = normalize( flipV ? -uvw.tangent_v : uvw.tangent_v );
+ vec3 normal = normalize( cross( tangentU, tangentV ) );
+
+ return( mix( normal, normalize( tangent.x * tangentU - tangent.y * tangentV + tangent.z * normal ), factor ) );
+}
+
+#include "textureCoordinateInfo.glsllib"
+
+//Simpler version built to run from UIC image data
+//In our case, we have already generated the texture coordinate x,y position
+//TODO - figure out if we need to manipulate tangent_u, tangent_v.
+vec3 defaultMaterialFileNormalTexture( in sampler2D sampler, in float factor, vec2 texCoord, vec3 tangent, vec3 binormal )
+{
+ // factor should be in [0,1] range
+ return tangentSpaceNormalTexture( sampler, clamp(factor, 0.0, 1.0), false, false
+ , textureCoordinateInfo( vec3( texCoord.x, texCoord.y, 0.0 ), tangent, binormal )
+ , vec2( 0.000000, 1.000000 ), vec2( 0.000000, 1.000000 )
+ , wrap_repeat, wrap_repeat);
+}
+
+#endif
diff --git a/res/effectlib/tessellationLinear.glsllib b/res/effectlib/tessellationLinear.glsllib
new file mode 100644
index 0000000..f854cc1
--- /dev/null
+++ b/res/effectlib/tessellationLinear.glsllib
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_LINEAR_GLSLLIB
+#define TESSELLATION_LINEAR_GLSLLIB
+
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+// global setup in main
+vec3 ctWorldPos[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( dot(faceNormal, ncd) );
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+
+ // adapative tessellation factor
+ float af = adaptiveCameraFactor( tessInner, tessEdge );
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, equal_spacing, ccw) in;
+
+vec4 tessShader ( )
+{
+ vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;
+ vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;
+ vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;
+ vec4 pos = p0 + p1 + p2;
+ return pos;
+}
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationLinearCM.glsllib b/res/effectlib/tessellationLinearCM.glsllib
new file mode 100644
index 0000000..d2bb90a
--- /dev/null
+++ b/res/effectlib/tessellationLinearCM.glsllib
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_LINEAR_CM_GLSLLIB
+#define TESSELLATION_LINEAR_CM_ GLSLLIB
+
+#include "tessellationLinear.glsllib"
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+#if QT3DS_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if QT3DS_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.x * varObjPosTC[0] + gl_TessCoord.y * varObjPosTC[1] + gl_TessCoord.z * varObjPosTC[2];
+ VARYING_NAME(varNormal) = gl_TessCoord.x * varNormalTC[0] + gl_TessCoord.y * varNormalTC[1] + gl_TessCoord.z * varNormalTC[2];
+
+#if QT3DS_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.x * varTexCoord0TC[0] + gl_TessCoord.y * varTexCoord0TC[1] + gl_TessCoord.z * varTexCoord0TC[2];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = gl_TessCoord.x * varTangentTC[0] + gl_TessCoord.y * varTangentTC[1] + gl_TessCoord.z * varTangentTC[2];
+ VARYING_NAME(varObjTangent) = gl_TessCoord.x * varObjTangentTC[0] + gl_TessCoord.y * varObjTangentTC[1] + gl_TessCoord.z * varObjTangentTC[2];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = gl_TessCoord.x * varBinormalTC[0] + gl_TessCoord.y * varBinormalTC[1] + gl_TessCoord.z * varBinormalTC[2];
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.x * varObjBinormalTC[0] + gl_TessCoord.y * varObjBinormalTC[1] + gl_TessCoord.z * varObjBinormalTC[2];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.x * varWorldPosTC[0] + gl_TessCoord.y * varWorldPosTC[1] + gl_TessCoord.z * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * VARYING_NAME(varNormal));
+}
+
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationNPatch.glsllib b/res/effectlib/tessellationNPatch.glsllib
new file mode 100644
index 0000000..62ec263
--- /dev/null
+++ b/res/effectlib/tessellationNPatch.glsllib
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_NPATCH_GLSLLIB
+#define TESSELLATION_NPATCH_GLSLLIB
+
+struct NPatchTessPatch
+{
+ float b210;
+ float b120;
+ float b021;
+ float b012;
+ float b102;
+ float b201;
+ float b111;
+ float n110;
+ float n011;
+ float n101;
+ float t110;
+ float t011;
+ float t101;
+};
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+layout(location=15) out NPatchTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctWorldPos[3];
+vec3 ctNorm[3];
+vec3 ctTangent[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( 0.2 + dot(faceNormal, ncd) ); // 0.2 is a conservative offset to account for curved surfaces
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+float adaptiveFeatureFactor( in float minTess, in float maxTess )
+{
+ vec3 adaptValue;
+ adaptValue[0] = clamp( dot(ctNorm[1], ctNorm[2]), -1.0, 1.0 );
+ adaptValue[1] = clamp( dot(ctNorm[2], ctNorm[0]), -1.0, 1.0 );
+ adaptValue[2] = clamp( dot(ctNorm[0], ctNorm[1]), -1.0, 1.0 );
+
+ //float af = min( adaptValue[0], min(adaptValue[1], adaptValue[2]) );
+ // map [-1, +1] range to [0, 1] range
+ float af = (adaptValue[gl_InvocationID] + 1.0) / 2.0;
+
+ af = mix( minTess, maxTess, 1.0 - af );
+
+ return af;
+}
+
+float getwij(int i, int j)
+{
+ return dot(gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz, ctNorm[i]);
+}
+
+float getvij(int i, int j)
+{
+ vec3 pji = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
+ vec3 nij = ctNorm[i] + ctNorm[j];
+
+ return 2.0*dot(pji, nij)/dot(pji, pji);
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ // setup control points
+ // notations and formulas see http://alex.vlachos.com/graphics/CurvedPNTriangles.pdf
+ // note we compute separate x,y,z component for each invocation
+ float b300 = gl_in[0].gl_Position[gl_InvocationID];
+ float b030 = gl_in[1].gl_Position[gl_InvocationID];
+ float b003 = gl_in[2].gl_Position[gl_InvocationID];
+ float n200 = ctNorm[0][gl_InvocationID];
+ float n020 = ctNorm[1][gl_InvocationID];
+ float n002 = ctNorm[2][gl_InvocationID];
+ float t200 = ctTangent[0][gl_InvocationID];
+ float t020 = ctTangent[1][gl_InvocationID];
+ float t002 = ctTangent[2][gl_InvocationID];
+
+ // compute tangent control points
+ tcTessPatch[gl_InvocationID].b210 = (2.0*b300 + b030 - getwij(0,1)*n200)/3.0;
+ tcTessPatch[gl_InvocationID].b120 = (2.0*b030 + b300 - getwij(1,0)*n020)/3.0;
+ tcTessPatch[gl_InvocationID].b021 = (2.0*b030 + b003 - getwij(1,2)*n020)/3.0;
+ tcTessPatch[gl_InvocationID].b012 = (2.0*b003 + b030 - getwij(2,1)*n002)/3.0;
+ tcTessPatch[gl_InvocationID].b102 = (2.0*b003 + b300 - getwij(2,0)*n002)/3.0;
+ tcTessPatch[gl_InvocationID].b201 = (2.0*b300 + b003 - getwij(0,2)*n200)/3.0;
+ // compute center control point
+ float E = ( tcTessPatch[gl_InvocationID].b210
+ + tcTessPatch[gl_InvocationID].b120
+ + tcTessPatch[gl_InvocationID].b021
+ + tcTessPatch[gl_InvocationID].b012
+ + tcTessPatch[gl_InvocationID].b102
+ + tcTessPatch[gl_InvocationID].b201 ) / 6.0;
+
+ float V = ( b300 + b030 + b003 ) / 3.0;
+ tcTessPatch[gl_InvocationID].b111 = E + (E-V)*0.5;
+
+ // compute normals
+ tcTessPatch[gl_InvocationID].n110 = n200 + n020 - getvij(0,1) * (b030 - b300);
+ tcTessPatch[gl_InvocationID].n011 = n020 + n002 - getvij(1,2) * (b003 - b030);
+ tcTessPatch[gl_InvocationID].n101 = n002 + n200 - getvij(2,0) * (b300 - b003);
+ // compute tangents
+ tcTessPatch[gl_InvocationID].t110 = t200 + t020 - getvij(0,1) * (b030 - b300);
+ tcTessPatch[gl_InvocationID].t011 = t020 + t002 - getvij(1,2) * (b003 - b030);
+ tcTessPatch[gl_InvocationID].t101 = t002 + t200 - getvij(2,0) * (b300 - b003);
+
+ // compute backface
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+
+ // adapative tessellation factor regarding features
+ float af = adaptiveFeatureFactor( tessInner, tessEdge );
+
+ //float cf = adaptiveCameraFactor( tessInner, tessEdge );
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, fractional_odd_spacing, ccw) in;
+
+layout(location=15) in NPatchTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctNorm[3];
+vec3 teNorm;
+vec3 ctTangent[3];
+vec3 teTangent;
+vec3 teBinormal;
+
+bool doLinear(int i, int j)
+{
+ /*
+ vec3 edgeji = gl_in[j].gl_Position.xyz - gl_in[i].gl_Position.xyz;
+
+ float di = sign( dot( ctNorm[i], edgeji ) );
+ float dj = sign( dot( ctNorm[j], -edgeji ) );
+
+ if ( di != dj )
+ return false;
+ else
+ return true;*/
+
+ // Always do linear normal interpolation for now
+ // Seems to produce always good results unless we would produce
+ // a s-shaped triangle.
+ return true;
+}
+
+vec4 tessShader ( )
+{
+ // pre compute square tesselation coord
+ vec3 tessSquared = gl_TessCoord * gl_TessCoord;
+ vec3 tessCubed = tessSquared * gl_TessCoord;
+
+ // combine control points
+ vec3 b210 = vec3(tcTessPatch[0].b210, tcTessPatch[1].b210, tcTessPatch[2].b210);
+ vec3 b120 = vec3(tcTessPatch[0].b120, tcTessPatch[1].b120, tcTessPatch[2].b120);
+ vec3 b021 = vec3(tcTessPatch[0].b021, tcTessPatch[1].b021, tcTessPatch[2].b021);
+ vec3 b012 = vec3(tcTessPatch[0].b012, tcTessPatch[1].b012, tcTessPatch[2].b012);
+ vec3 b102 = vec3(tcTessPatch[0].b102, tcTessPatch[1].b102, tcTessPatch[2].b102);
+ vec3 b201 = vec3(tcTessPatch[0].b201, tcTessPatch[1].b201, tcTessPatch[2].b201);
+ vec3 b111 = vec3(tcTessPatch[0].b111, tcTessPatch[1].b111, tcTessPatch[2].b111);
+
+ // combine control normals
+ vec3 n110 = vec3(tcTessPatch[0].n110, tcTessPatch[1].n110, tcTessPatch[2].n110);
+ vec3 n011 = vec3(tcTessPatch[0].n011, tcTessPatch[1].n011, tcTessPatch[2].n011);
+ vec3 n101 = vec3(tcTessPatch[0].n101, tcTessPatch[1].n101, tcTessPatch[2].n101);
+
+ // combine control tangents
+ vec3 t110 = vec3(tcTessPatch[0].t110, tcTessPatch[1].t110, tcTessPatch[2].t110);
+ vec3 t011 = vec3(tcTessPatch[0].t011, tcTessPatch[1].t011, tcTessPatch[2].t011);
+ vec3 t101 = vec3(tcTessPatch[0].t101, tcTessPatch[1].t101, tcTessPatch[2].t101);
+
+ // NPatch normal
+ if ( doLinear( 0, 1 ) == true )
+ {
+ // linear normal
+ teNorm = ctNorm[0] * gl_TessCoord[2]
+ + ctNorm[1] * gl_TessCoord[0]
+ + ctNorm[2] * gl_TessCoord[1];
+ // NPatch tangent
+ teTangent = ctTangent[0] * gl_TessCoord[2]
+ + ctTangent[1] * gl_TessCoord[0]
+ + ctTangent[2] * gl_TessCoord[1];
+ }
+ else
+ {
+ // quadratic normal
+ teNorm = ctNorm[0] * tessSquared[2]
+ + ctNorm[1] * tessSquared[0]
+ + ctNorm[2] * tessSquared[1]
+ + n110*gl_TessCoord[2] * gl_TessCoord[0]
+ + n011*gl_TessCoord[0] * gl_TessCoord[1]
+ + n101*gl_TessCoord[2] * gl_TessCoord[1];
+
+ // NPatch tangent
+ teTangent = ctTangent[0] * tessSquared[2]
+ + ctTangent[1] * tessSquared[0]
+ + ctTangent[2] * tessSquared[1]
+ + t110*gl_TessCoord[2] * gl_TessCoord[0]
+ + t011*gl_TessCoord[0] * gl_TessCoord[1]
+ + t101*gl_TessCoord[2] * gl_TessCoord[1];
+ }
+
+ // NPatch binormal
+ teBinormal = cross( teNorm, teTangent );
+
+ // npatch interpolated position
+ vec3 finalPos = gl_in[0].gl_Position.xyz * tessCubed[2]
+ + gl_in[1].gl_Position.xyz * tessCubed[0]
+ + gl_in[2].gl_Position.xyz * tessCubed[1]
+ + b210 * 3.0 * tessSquared[2] * gl_TessCoord[0]
+ + b120 * 3.0 * tessSquared[0] * gl_TessCoord[2]
+ + b201 * 3.0 * tessSquared[2] * gl_TessCoord[1]
+ + b021 * 3.0 * tessSquared[0] * gl_TessCoord[1]
+ + b102 * 3.0 * tessSquared[1] * gl_TessCoord[2]
+ + b012 * 3.0 * tessSquared[1] * gl_TessCoord[0]
+ + b111 * 6.0 * gl_TessCoord[0] * gl_TessCoord[1] * gl_TessCoord[2];
+
+ return vec4( finalPos, 1.0 );
+}
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationNPatchCM.glsllib b/res/effectlib/tessellationNPatchCM.glsllib
new file mode 100644
index 0000000..4616b58
--- /dev/null
+++ b/res/effectlib/tessellationNPatchCM.glsllib
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_NPATCH_CM_GLSLLIB
+#define TESSELLATION_NPATCH_CM_GLSLLIB GLSLLIB
+
+
+#include "tessellationNPatch.glsllib"
+
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+ ctNorm[0] = varNormal[0];
+ ctNorm[1] = varNormal[1];
+ ctNorm[2] = varNormal[2];
+#if QT3DS_ENABLE_TEXTAN
+ ctTangent[0] = varObjTangent[0];
+ ctTangent[1] = varObjTangent[1];
+ ctTangent[2] = varObjTangent[2];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if QT3DS_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+
+ ctNorm[0] = varNormalTC[0];
+ ctNorm[1] = varNormalTC[1];
+ ctNorm[2] = varNormalTC[2];
+#if QT3DS_ENABLE_TEXTAN
+ ctTangent[0] = varObjTangentTC[0];
+ ctTangent[1] = varObjTangentTC[1];
+ ctTangent[2] = varObjTangentTC[2];
+#endif
+
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.z * varObjPosTC[0] + gl_TessCoord.x * varObjPosTC[1] + gl_TessCoord.y * varObjPosTC[2];
+
+#if QT3DS_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.z * varTexCoord0TC[0] + gl_TessCoord.x * varTexCoord0TC[1] + gl_TessCoord.y * varTexCoord0TC[2];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.z * varWorldPosTC[0] + gl_TessCoord.x * varWorldPosTC[1] + gl_TessCoord.y * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * teNorm);
+
+#if QT3DS_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = normalize(normal_matrix * teTangent);
+ VARYING_NAME(varObjTangent) = gl_TessCoord.z * varObjTangentTC[0] + gl_TessCoord.x * varObjTangentTC[1] + gl_TessCoord.y * varObjTangentTC[2];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = normalize(normal_matrix * teBinormal);
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.z * varObjBinormalTC[0] + gl_TessCoord.x * varObjBinormalTC[1] + gl_TessCoord.y * varObjBinormalTC[2];
+#endif
+}
+
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationPath.glsllib b/res/effectlib/tessellationPath.glsllib
new file mode 100644
index 0000000..17b87b0
--- /dev/null
+++ b/res/effectlib/tessellationPath.glsllib
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_PATH_GLSLLIB
+#define TESSELLATION_PATH_GLSLLIB
+
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 5) out;
+
+void tessShader ( in float edgeTessAmount, float innerTessAmount )
+{
+ gl_TessLevelOuter[0] = innerTessAmount;
+ gl_TessLevelOuter[1] = edgeTessAmount;
+ gl_TessLevelOuter[2] = innerTessAmount;
+ gl_TessLevelOuter[3] = edgeTessAmount;
+
+ gl_TessLevelInner[0] = edgeTessAmount / 2.0;
+ gl_TessLevelInner[1] = innerTessAmount;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (quads, equal_spacing, cw) in;
+
+vec2 getTangent(vec2 p0, vec2 p1, vec2 p2, vec2 p3, float t)
+{
+ // derivative
+ float dbt0 = -3.0 * (1.0 - t) * (1.0 - t);
+ float dbt1 = 3.0 * (1.0 - t) * (1.0 - 3.0 * t);
+ float dbt2 = 3.0 * t * (2.0 - 3.0 * t);
+ float dbt3 = 3.0 * t * t;
+
+ // tangent on curve
+ return normalize( dbt0 * p0 + dbt1 * p1 + dbt2 * p2 + dbt3 * p3 );
+}
+//An exact cross product would involve normalizing dx,dy. Since
+//this algorithm needs merely the sign, normalization is not necessary.
+float roughCrossProd( vec2 prev, vec2 point, vec2 next )
+{
+ vec2 inDxDy = point - prev;
+ vec2 outDxDy = next - point;
+ return inDxDy.x * outDxDy.y - inDxDy.y * outDxDy.x;
+}
+
+//The incoming corss product tells us both if we should do a seam merge
+//and if the merge is above or below point in gl_TessCoord.y space; we know the
+//anchor point is at .5 gl_TessCoord.y space.
+vec3 computeAdjoiningFactors( float cross, vec2 adjoining, vec2 point, float tessY )
+{
+ vec3 retval = vec3( 0.0, 0.0, 0.0 );
+ float multiplier = cross < 0.0 ? 1.0 : -1.0;
+ float weight = abs(cross) > 0.001 ? multiplier * ( ( tessY - .5 )/ .5 ) : 0.0;
+ retval.z = weight > 0.0 ? 1.0 : 0.0;
+ retval.xy = mix( point, adjoining, weight );
+ return retval;
+}
+
+#define NO_TAPER 0
+#define BEGIN_TAPER 1
+#define END_TAPER 2
+
+//Tapering is done by interpolating the path width somewhat cleverly.
+float getTaperResult( float inIncomingValue, float inBeginValue, float inEndValue, vec2 taperData, uint inMode )
+{
+ float mixInfo = mix( taperData.x, taperData.y, gl_TessCoord.x );
+ float theValueMixer = inMode == BEGIN_TAPER ? inBeginValue : inEndValue;
+ return mix( theValueMixer, inIncomingValue, mixInfo );
+}
+
+uniform vec2 beginTaperInfo;
+uniform vec2 endTaperInfo;
+
+struct STessShaderResult
+{
+ vec3 m_Position;
+ vec2 m_TexCoord;
+ vec2 m_Tangent;
+ vec2 m_Binormal;
+ float m_Opacity;
+};
+
+STessShaderResult tessShader ( float inPathWidth )
+{
+ vec2 p1 = gl_in[0].gl_Position.xy;
+ vec2 c1 = gl_in[0].gl_Position.zw; //c1
+ vec2 c2 = gl_in[1].gl_Position.xy; //c2
+ vec2 p2 = gl_in[1].gl_Position.zw;
+ vec4 taperData = gl_in[3].gl_Position;
+ vec2 udata = gl_in[4].gl_Position.xy;
+
+ //Adjust width for taper if necessary.
+ inPathWidth = taperData.z > 0.0 ? getTaperResult( inPathWidth, beginTaperInfo.x, endTaperInfo.x, taperData.xy, uint(taperData.z) ) : inPathWidth;
+
+ float adjoiningWeight = 0.0;
+ vec2 adjoining = vec2( 0.0, 0.0 );
+ if ( gl_TessCoord.x == floor(gl_TessCoord.x) ) // gl_TessCord.x either 0.0 or 1.0
+ {
+ vec2 point, cross1, cross2;
+ if ( gl_TessCoord.x == 0.0 )
+ {
+ adjoining = gl_in[2].gl_Position.xy;
+ point = p1;
+ cross1 = adjoining;
+ cross2 = c1;
+ }
+ else // gl_TessCoord.x == 1.0
+ {
+ adjoining = gl_in[2].gl_Position.zw;
+ point = p2;
+ cross1 = c2;
+ cross2 = adjoining;
+ }
+ float cross = roughCrossProd( cross1, point, cross2 );
+ vec3 adjoiningFactors = computeAdjoiningFactors( cross, adjoining, point, gl_TessCoord.y );
+ adjoining = adjoiningFactors.xy;
+ adjoiningWeight = adjoiningFactors.z;
+ }
+
+ float v = gl_TessCoord.x;
+ // cubic basis function calculated from v.
+ float bv0 = (1.0 - v) * (1.0 - v) * (1.0 - v);
+ float bv1 = 3.0 * v * (1.0 - v) * (1.0 - v);
+ float bv2 = 3.0 * v * v * (1.0 - v);
+ float bv3 = v * v * v;
+
+ //u ranges from 0 - 1. What we want is to
+ //have u range from -1,1.
+ float u = 2.0 * ( gl_TessCoord.y - .5 );
+
+ vec2 tangent = getTangent( p1, c1, c2, p2, v );
+ vec2 normal = vec2( tangent.y, -tangent.x );
+
+ vec2 offset = normal * inPathWidth * u;
+
+ vec2 pointOnPath = bv0*p1 + bv1*c1 + bv2*c2 + bv3*p2;
+
+ vec2 finalPosXY = offset + pointOnPath;
+
+ STessShaderResult retval;
+ retval.m_Position = vec3( mix( finalPosXY, adjoining, adjoiningWeight), 0.0 );
+ retval.m_Opacity = taperData.z > 0.0 ? getTaperResult( 1.0, beginTaperInfo.y, endTaperInfo.y, taperData.xy, uint(taperData.z) ) : 1.0;
+
+ // cubic interpolation of the texture coords
+ retval.m_TexCoord.x = mix( udata.x, udata.y, v );
+ retval.m_TexCoord.y = gl_TessCoord.y;
+ retval.m_Tangent = tangent;
+ retval.m_Binormal = normal;
+
+ return retval;
+}
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationPhong.glsllib b/res/effectlib/tessellationPhong.glsllib
new file mode 100644
index 0000000..98a683d
--- /dev/null
+++ b/res/effectlib/tessellationPhong.glsllib
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_PHONG_GLSLLIB
+#define TESSELLATION_PHONG_GLSLLIB
+
+struct PhongTessPatch
+{
+ float projIJ;
+ float projJK;
+ float projIK;
+};
+
+#if TESSELLATION_CONTROL_SHADER
+layout (vertices = 3) out;
+
+layout(location = 15) out PhongTessPatch tcTessPatch[];
+
+// global setup in main
+vec3 ctWorldPos[3];
+vec3 ctNorm[3];
+
+uniform vec3 camera_position;
+uniform vec2 distanceRange;
+uniform float disableCulling;
+
+float isBackFace()
+{
+ vec3 faceNormal = normalize( cross( ctWorldPos[2] - ctWorldPos[0], ctWorldPos[1] - ctWorldPos[0] ) );
+
+ vec3 ncd = normalize( ctWorldPos[0] - camera_position );
+
+ return sign( 0.2 + dot(faceNormal, ncd) ); // 0.2 is a conservative offset to account for curved surfaces
+}
+
+float adaptiveCameraFactor( in float minTess, in float maxTess )
+{
+ float distanceValue0 = distance( camera_position, ctWorldPos[0] );
+ float distanceValue1 = distance( camera_position, ctWorldPos[1] );
+ float distanceValue2 = distance( camera_position, ctWorldPos[2] );
+
+ float range = distanceRange[1] - distanceRange[0];
+
+ vec3 edgeDistance;
+ edgeDistance[0] = ((distanceValue1 + distanceValue2) / 2.0) / range;
+ edgeDistance[1] = ((distanceValue2 + distanceValue0) / 2.0) / range;
+ edgeDistance[2] = ((distanceValue0 + distanceValue1) / 2.0) / range;
+
+ edgeDistance = clamp( edgeDistance, vec3(0.0), vec3(1.0) );
+
+ //float af = mix( minTess, maxTess, 1.0 - edgeDistance[gl_InvocationID] );
+ float af = 1.0 - edgeDistance[gl_InvocationID];
+ af = clamp( af*af*maxTess , minTess, maxTess );
+
+ return af;
+}
+
+float adaptiveFeatureFactor( in float minTess, in float maxTess )
+{
+ vec3 adaptValue;
+ adaptValue[0] = clamp( dot(ctNorm[1], ctNorm[2]), -1.0, 1.0 );
+ adaptValue[1] = clamp( dot(ctNorm[2], ctNorm[0]), -1.0, 1.0 );
+ adaptValue[2] = clamp( dot(ctNorm[0], ctNorm[1]), -1.0, 1.0 );
+
+ //float af = min( adaptValue[0], min(adaptValue[1], adaptValue[2]) );
+ // map [-1, +1] range to [0, 1] range
+ float af = (adaptValue[gl_InvocationID] + 1.0) / 2.0;
+
+ af = mix( minTess, maxTess, 1.0 - af );
+
+ return af;
+}
+
+float mapToTangentPlane(int i, vec3 q)
+{
+ vec3 q_minus_p = q - gl_in[i].gl_Position.xyz;
+ return q[gl_InvocationID] - dot(q_minus_p, ctNorm[i]) * ctNorm[i][gl_InvocationID];
+}
+
+void tessShader ( in float tessEdge, in float tessInner )
+{
+ // compute projections separate for each xyz component
+ tcTessPatch[gl_InvocationID].projIJ = mapToTangentPlane(0, gl_in[1].gl_Position.xyz) + mapToTangentPlane(1, gl_in[0].gl_Position.xyz);
+ tcTessPatch[gl_InvocationID].projJK = mapToTangentPlane(1, gl_in[2].gl_Position.xyz) + mapToTangentPlane(2, gl_in[1].gl_Position.xyz);
+ tcTessPatch[gl_InvocationID].projIK = mapToTangentPlane(2, gl_in[0].gl_Position.xyz) + mapToTangentPlane(0, gl_in[2].gl_Position.xyz);
+
+ // compute backface
+ float bf = isBackFace();
+ bf = max(disableCulling, bf);
+ // adapative tessellation factor regarding features
+ float af = adaptiveFeatureFactor( tessInner, tessEdge );
+ // adapative tessellation factor regarding camera
+ //float cf = adaptiveFeatureFactor( tessInner, tessEdge );
+
+ // the camera tess factor is the limit
+ //af = min(af, cf);
+
+ // Calculate the tessellation levels
+ gl_TessLevelInner[0] = af * bf;
+ gl_TessLevelOuter[gl_InvocationID] = af * bf;
+}
+
+#endif
+
+#if TESSELLATION_EVALUATION_SHADER
+layout (triangles, equal_spacing, ccw) in;
+
+layout(location = 15) in PhongTessPatch tcTessPatch[];
+
+uniform float phongBlend;
+
+vec4 tessShader ( )
+{
+ // pre compute square tesselation coord
+ vec3 tessSquared = gl_TessCoord * gl_TessCoord;
+
+ // barycentric linear position
+ vec3 linearPos = gl_TessCoord.x * gl_in[0].gl_Position.xyz
+ + gl_TessCoord.y * gl_in[1].gl_Position.xyz
+ + gl_TessCoord.z * gl_in[2].gl_Position.xyz;
+
+ // projective terms
+ vec3 projJI = vec3(tcTessPatch[0].projIJ, tcTessPatch[1].projIJ, tcTessPatch[2].projIJ);
+ vec3 projKJ = vec3(tcTessPatch[0].projJK, tcTessPatch[1].projJK, tcTessPatch[2].projJK);
+ vec3 projIK = vec3(tcTessPatch[0].projIK, tcTessPatch[1].projIK, tcTessPatch[2].projIK);
+
+ // phong interpolated position
+ vec3 phongPos = tessSquared.x * gl_in[0].gl_Position.xyz
+ + tessSquared.y * gl_in[1].gl_Position.xyz
+ + tessSquared.z * gl_in[2].gl_Position.xyz
+ + gl_TessCoord.x * gl_TessCoord.y * projJI
+ + gl_TessCoord.y * gl_TessCoord.z * projKJ
+ + gl_TessCoord.z * gl_TessCoord.x * projIK;
+
+ // final blend between linear and phong interpolation
+ vec3 finalPos = (1.0-phongBlend)*linearPos + phongBlend*phongPos;
+
+ return vec4( finalPos, 1.0 );
+}
+#endif
+
+#endif
+
diff --git a/res/effectlib/tessellationPhongCM.glsllib b/res/effectlib/tessellationPhongCM.glsllib
new file mode 100644
index 0000000..1374a63
--- /dev/null
+++ b/res/effectlib/tessellationPhongCM.glsllib
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** 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 TESSELLATION_PHONG_CM_GLSLLIB
+#define TESSELLATION_PHONG_CM_ GLSLLIB
+
+
+#include "tessellationPhong.glsllib"
+
+
+#if TESSELLATION_CONTROL_SHADER
+
+uniform float tessLevelOuter;
+uniform float tessLevelInner;
+
+attribute vec3 varNormal[];
+attribute vec3 varObjPos[];
+
+varying vec3 varNormalTC[];
+varying vec3 varObjPosTC[];
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0[];
+varying vec3 varTexCoord0TC[];
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangent[];
+attribute vec3 varObjTangent[];
+varying vec3 varTangentTC[];
+varying vec3 varObjTangentTC[];
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormal[];
+attribute vec3 varObjBinormal[];
+varying vec3 varBinormalTC[];
+varying vec3 varObjBinormalTC[];
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPos[];
+varying vec3 varWorldPosTC[];
+#endif
+
+void main() {
+
+#if QT3DS_ENABLE_WORLD_POSITION
+ ctWorldPos[0] = varWorldPos[0];
+ ctWorldPos[1] = varWorldPos[1];
+ ctWorldPos[2] = varWorldPos[2];
+#endif
+ ctNorm[0] = varNormal[0];
+ ctNorm[1] = varNormal[1];
+ ctNorm[2] = varNormal[2];
+
+ gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ tessShader( tessLevelOuter, tessLevelInner);
+
+ varObjPosTC[gl_InvocationID] = varObjPos[gl_InvocationID];
+ varNormalTC[gl_InvocationID] = varNormal[gl_InvocationID];
+
+#if QT3DS_ENABLE_UV0
+ varTexCoord0TC[gl_InvocationID] = varTexCoord0[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangentTC[gl_InvocationID] = varTangent[gl_InvocationID];
+ varObjTangentTC[gl_InvocationID] = varObjTangent[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormalTC[gl_InvocationID] = varBinormal[gl_InvocationID];
+ varObjBinormalTC[gl_InvocationID] = varObjBinormal[gl_InvocationID];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPosTC[gl_InvocationID] = varWorldPos[gl_InvocationID];
+#endif
+}
+
+#endif
+
+
+#if TESSELLATION_EVALUATION_SHADER
+
+#if (GEOMETRY_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName
+#endif
+
+uniform mat3 normal_matrix;
+uniform mat4 model_view_projection_matrix;
+
+attribute vec3 varNormalTC[];
+attribute vec3 varObjPosTC[];
+
+varying vec3 VARYING_NAME(varNormal);
+varying vec3 VARYING_NAME(varObjPos);
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 varTexCoord0TC[];
+varying vec3 VARYING_NAME(varTexCoord0);
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 varTangentTC[];
+attribute vec3 varObjTangentTC[];
+varying vec3 VARYING_NAME(varTangent);
+varying vec3 VARYING_NAME(varObjTangent);
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 varBinormalTC[];
+attribute vec3 varObjBinormalTC[];
+varying vec3 VARYING_NAME(varBinormal);
+varying vec3 VARYING_NAME(varObjBinormal);
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 varWorldPosTC[];
+varying vec3 VARYING_NAME(varWorldPos);
+#endif
+
+void main() {
+ vec4 pos = tessShader( );
+
+ gl_Position = model_view_projection_matrix * pos;
+
+ VARYING_NAME(varObjPos) = gl_TessCoord.x * varObjPosTC[0] + gl_TessCoord.y * varObjPosTC[1] + gl_TessCoord.z * varObjPosTC[2];
+ VARYING_NAME(varNormal) = gl_TessCoord.x * varNormalTC[0] + gl_TessCoord.y * varNormalTC[1] + gl_TessCoord.z * varNormalTC[2];
+
+#if QT3DS_ENABLE_UV0
+ VARYING_NAME(varTexCoord0) = gl_TessCoord.x * varTexCoord0TC[0] + gl_TessCoord.y * varTexCoord0TC[1] + gl_TessCoord.z * varTexCoord0TC[2];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ VARYING_NAME(varTangent) = gl_TessCoord.x * varTangentTC[0] + gl_TessCoord.y * varTangentTC[1] + gl_TessCoord.z * varTangentTC[2];
+ VARYING_NAME(varObjTangent) = gl_TessCoord.x * varObjTangentTC[0] + gl_TessCoord.y * varObjTangentTC[1] + gl_TessCoord.z * varObjTangentTC[2];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ VARYING_NAME(varBinormal) = gl_TessCoord.x * varBinormalTC[0] + gl_TessCoord.y * varBinormalTC[1] + gl_TessCoord.z * varBinormalTC[2];
+ VARYING_NAME(varObjBinormal) = gl_TessCoord.x * varObjBinormalTC[0] + gl_TessCoord.y * varObjBinormalTC[1] + gl_TessCoord.z * varObjBinormalTC[2];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ VARYING_NAME(varWorldPos) = gl_TessCoord.x * varWorldPosTC[0] + gl_TessCoord.y * varWorldPosTC[1] + gl_TessCoord.z * varWorldPosTC[2];
+#endif
+
+ VARYING_NAME(varNormal) = normalize(normal_matrix * VARYING_NAME(varNormal));
+}
+
+#endif
+
+#endif
+
diff --git a/res/effectlib/textureCoordinateInfo.glsllib b/res/effectlib/textureCoordinateInfo.glsllib
new file mode 100644
index 0000000..a90ffbe
--- /dev/null
+++ b/res/effectlib/textureCoordinateInfo.glsllib
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 TEXTURE_COORDINATE_INFO_GLSLLIB
+#define TEXTURE_COORDINATE_INFO_GLSLLIB
+
+#ifdef QT3DS_DEFINE_API
+
+struct texture_coordinate_info
+{
+ vec3 position;
+ vec3 tangent_u;
+ vec3 tangent_v;
+};
+
+#endif
+
+texture_coordinate_info textureCoordinateInfo( in vec3 pos, in vec3 tangentU, in vec3 tangentV )
+{
+ texture_coordinate_info tci;
+ tci.position = pos;
+ tci.tangent_u = normalize( tangentU );
+ tci.tangent_v = normalize( tangentV );
+ return( tci );
+}
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/transformCoordinate.glsllib b/res/effectlib/transformCoordinate.glsllib
new file mode 100644
index 0000000..ccdf7d0
--- /dev/null
+++ b/res/effectlib/transformCoordinate.glsllib
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** 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 TRANSFORM_COORDINATE_GLSLLIB
+#define TRANSFORM_COORDINATE_GLSLLIB
+
+texture_coordinate_info transformCoordinate( in mat4 transform, in texture_coordinate_info coordinate )
+{
+ texture_coordinate_info tci;
+ tci.position = ( transform * vec4( coordinate.position, 1.0 ) ).xyz;
+ tci.tangent_u = ( transform * vec4( coordinate.tangent_u, 0.0 ) ).xyz;
+ tci.tangent_v = ( transform * vec4( coordinate.tangent_v, 0.0 ) ).xyz;
+ return( tci );
+}
+
+#endif
diff --git a/res/effectlib/vertexFragmentBase.glsllib b/res/effectlib/vertexFragmentBase.glsllib
new file mode 100644
index 0000000..add11bb
--- /dev/null
+++ b/res/effectlib/vertexFragmentBase.glsllib
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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 VERTEX_FRAGMENT_BASE_GLSLLIB
+#define VERTEX_FRAGMENT_BASE_GLSLLIB
+
+ //FRAGMENT_SHADER
+ uniform vec3 camera_position; //position in world space of the camera
+
+// add global variables
+vec3 normal;
+vec3 surfNormal;
+vec3 texCoord0;
+vec3 tangent;
+vec3 binormal;
+vec3 viewDir;
+
+
+// add shader input
+
+void initializeBaseFragmentVariables()
+{
+ normal = normalize( varNormal );
+ surfNormal = normalize( varNormal );
+
+ texCoord0 = vec3( varTexCoord0.xy, 1.0 );
+ tangent = normalize( varTangent );
+
+ binormal = normalize( varBinormal );
+
+ viewDir = normalize( camera_position - varWorldPos );
+}
+
+#endif
diff --git a/res/effectlib/viewProperties.glsllib b/res/effectlib/viewProperties.glsllib
new file mode 100644
index 0000000..ef6b01f
--- /dev/null
+++ b/res/effectlib/viewProperties.glsllib
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** 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 VIEW_PROPERTIES_GLSLLIB
+#define VIEW_PROPERTIES_GLSLLIB
+
+uniform mat4 view_projection_matrix;
+uniform mat4 view_matrix;
+uniform vec2 camera_properties; //near clip x, far clip y
+#ifndef SSAO_CUSTOM_MATERIAL_GLSLLIB
+uniform vec3 camera_position; //position in world space of the camera
+#endif
+
+#endif \ No newline at end of file
diff --git a/res/effectlib/weightedLayer.glsllib b/res/effectlib/weightedLayer.glsllib
new file mode 100644
index 0000000..781ffac
--- /dev/null
+++ b/res/effectlib/weightedLayer.glsllib
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+vec4 weightedLayer( in float weight, in vec3 layercolor, in vec4 layer, in vec4 base, in float alpha )
+{
+ return vec4( mix( base.rgb, layer.rgb * layercolor, weight ), alpha );
+}
+
diff --git a/res/effectlib/wireframeCM.glsllib b/res/effectlib/wireframeCM.glsllib
new file mode 100644
index 0000000..fcbf7e9
--- /dev/null
+++ b/res/effectlib/wireframeCM.glsllib
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** 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 WIREFRAME_CM_GLSLLIB
+#define WIREFRAME_CM_GLSLLIB
+
+#ifdef GL_ES
+precision highp float;
+precision highp int;
+#endif
+
+#if (TESSELLATION_EVALUATION_SHADER == 1)
+#define VARYING_NAME(varyingName) varyingName##TE
+#else
+#define VARYING_NAME(varyingName) varyingName##VX
+#endif
+
+attribute vec3 VARYING_NAME(varNormal)[];
+attribute vec3 VARYING_NAME(varObjPos)[];
+
+varying vec3 varNormal;
+varying vec3 varObjPos;
+
+#if QT3DS_ENABLE_UV0
+attribute vec3 VARYING_NAME(varTexCoord0)[];
+varying vec3 varTexCoord0;
+#endif
+
+#if QT3DS_ENABLE_TEXTAN
+attribute vec3 VARYING_NAME(varTangent)[];
+attribute vec3 VARYING_NAME(varObjTangent)[];
+varying vec3 varTangent;
+varying vec3 varObjTangent;
+#endif
+
+#if QT3DS_ENABLE_BINORMAL
+attribute vec3 VARYING_NAME(varBinormal)[];
+attribute vec3 VARYING_NAME(varObjBinormal)[];
+varying vec3 varBinormal;
+varying vec3 varObjBinormal;
+#endif
+
+#if QT3DS_ENABLE_WORLD_POSITION
+attribute vec3 VARYING_NAME(varWorldPos)[];
+varying vec3 varWorldPos;
+#endif
+
+varying vec3 varEdgeDistance;
+
+uniform mat4 viewport_matrix;
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices = 3) out;
+
+void main()
+{
+ // how this all work see http://developer.download.nvidia.com/SDK/10.5/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf
+ // project points to screen space
+ vec3 p0 = vec3(viewport_matrix * (gl_in[0].gl_Position / gl_in[0].gl_Position.w));
+ vec3 p1 = vec3(viewport_matrix * (gl_in[1].gl_Position / gl_in[1].gl_Position.w));
+ vec3 p2 = vec3(viewport_matrix * (gl_in[2].gl_Position / gl_in[2].gl_Position.w));
+ // compute triangle heights
+ float e1 = length(p1 - p2);
+ float e2 = length(p2 - p0);
+ float e3 = length(p1 - p0);
+ float alpha = acos( (e2*e2 + e3*e3 - e1*e1) / (2.0*e2*e3) );
+ float beta = acos( (e1*e1 + e3*e3 - e2*e2) / (2.0*e1*e3) );
+ float ha = abs( e3 * sin( beta ) );
+ float hb = abs( e3 * sin( alpha ) );
+ float hc = abs( e2 * sin( alpha ) );
+
+
+ // vertex 0
+ varEdgeDistance = vec3(ha*gl_in[0].gl_Position.w, 0.0, 0.0);
+ varNormal = VARYING_NAME(varNormal)[0];
+ varObjPos = VARYING_NAME(varObjPos)[0];
+#if QT3DS_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[0];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[0];
+ varObjTangent = VARYING_NAME(varObjTangent)[0];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[0];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[0];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[0];
+#endif
+
+ gl_Position = gl_in[0].gl_Position;
+ EmitVertex();
+
+ // vertex 1
+ varEdgeDistance = vec3(0.0, hb*gl_in[1].gl_Position.w, 0.0);
+ varNormal = VARYING_NAME(varNormal)[1];
+ varObjPos = VARYING_NAME(varObjPos)[1];
+#if QT3DS_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[1];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[1];
+ varObjTangent = VARYING_NAME(varObjTangent)[1];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[1];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[1];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[1];
+#endif
+
+ gl_Position = gl_in[1].gl_Position;
+ EmitVertex();
+
+ // vertex 2
+ varEdgeDistance = vec3(0.0, 0.0, hc*gl_in[2].gl_Position.w);
+ varNormal = VARYING_NAME(varNormal)[2];
+ varObjPos = VARYING_NAME(varObjPos)[2];
+#if QT3DS_ENABLE_UV0
+ varTexCoord0 = VARYING_NAME(varTexCoord0)[2];
+#endif
+#if QT3DS_ENABLE_TEXTAN
+ varTangent = VARYING_NAME(varTangent)[2];
+ varObjTangent = VARYING_NAME(varObjTangent)[2];
+#endif
+#if QT3DS_ENABLE_BINORMAL
+ varBinormal = VARYING_NAME(varBinormal)[2];
+ varObjBinormal = VARYING_NAME(varObjBinormal)[2];
+#endif
+#if QT3DS_ENABLE_WORLD_POSITION
+ varWorldPos = VARYING_NAME(varWorldPos)[2];
+#endif
+
+ gl_Position = gl_in[2].gl_Position;
+ EmitVertex();
+
+ EndPrimitive();
+}
+
+#endif