diff options
author | Määttä Antti <antti.maatta@qt.io> | 2018-02-27 14:42:23 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2018-04-19 13:51:30 +0000 |
commit | e8828cb864799150aa4b536268e42638c81d96a4 (patch) | |
tree | 3fa169a7a530715aa56e966c62fa2359d7e99577 /res | |
parent | 91aa5b48f30da0688db3a00a7ef1fea29c8f5e05 (diff) |
Add opengl es 2 support
Adds effectlib changes from 1.1 runtime.
Change-Id: I1314974d03af37d0c8d78c5832812915e1d45884
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'res')
-rw-r--r-- | res/effectlib/gles2/SSAOCustomMaterial.glsllib | 100 | ||||
-rw-r--r-- | res/effectlib/gles2/defaultMaterialBumpNoLod.glsllib | 52 | ||||
-rw-r--r-- | res/effectlib/gles2/evalEnvironmentMap.glsllib | 37 | ||||
-rw-r--r-- | res/effectlib/gles2/funcareaLightVars.glsllib | 29 | ||||
-rw-r--r-- | res/effectlib/gles2/funcsampleLightVars.glsllib | 27 | ||||
-rw-r--r-- | res/effectlib/gles2/microfacetBSDF.glsllib | 233 | ||||
-rw-r--r-- | res/effectlib/gles2/monoChannel.glsllib | 58 | ||||
-rw-r--r-- | res/effectlib/gles2/refraction.glsllib | 87 | ||||
-rw-r--r-- | res/effectlib/gles2/sampleProbe.glsllib | 482 | ||||
-rw-r--r-- | res/effectlib/gles2/shadowMapping.glsllib | 106 | ||||
-rw-r--r-- | res/effectlib/gles2/tangentSpaceNormalTexture.glsllib | 97 |
11 files changed, 1308 insertions, 0 deletions
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..8f47e97 --- /dev/null +++ b/res/effectlib/gles2/funcareaLightVars.glsllib @@ -0,0 +1,29 @@ +#define MAX_AREA_LIGHTS 8 + +// 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..62a65f3 --- /dev/null +++ b/res/effectlib/gles2/funcsampleLightVars.glsllib @@ -0,0 +1,27 @@ + +#define MAX_NUM_LIGHTS 8 + +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 |